chiark / gitweb /
cgroup: always validate cgroup controller names
[elogind.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 (controller && !cg_controller_is_valid(controller, true))
514                 return -EINVAL;
515
516         if (_unlikely_(!good)) {
517                 int r;
518
519                 r = path_is_mount_point("/sys/fs/cgroup", false);
520                 if (r <= 0)
521                         return r < 0 ? r : -ENOENT;
522
523                 /* Cache this to save a few stat()s */
524                 good = true;
525         }
526
527         p = controller ? normalize_controller(controller) : NULL;
528
529         return join_path(p, path, suffix, fs);
530 }
531
532 static int check_hierarchy(const char *p) {
533         char *cc;
534
535         assert(p);
536
537         /* Check if this controller actually really exists */
538         cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
539         strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
540         if (access(cc, F_OK) < 0)
541                 return -errno;
542
543         return 0;
544 }
545
546 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
547         const char *p;
548         int r;
549
550         assert(fs);
551
552         if (!cg_controller_is_valid(controller, true))
553                 return -EINVAL;
554
555         /* Normalize the controller syntax */
556         p = normalize_controller(controller);
557
558         /* Check if this controller actually really exists */
559         r = check_hierarchy(p);
560         if (r < 0)
561                 return r;
562
563         return join_path(p, path, suffix, fs);
564 }
565
566 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
567         char *p;
568         bool is_sticky;
569
570         if (typeflag != FTW_DP)
571                 return 0;
572
573         if (ftwbuf->level < 1)
574                 return 0;
575
576         p = strappend(path, "/tasks");
577         if (!p) {
578                 errno = ENOMEM;
579                 return 1;
580         }
581
582         is_sticky = file_is_priv_sticky(p) > 0;
583         free(p);
584
585         if (is_sticky)
586                 return 0;
587
588         rmdir(path);
589         return 0;
590 }
591
592 int cg_trim(const char *controller, const char *path, bool delete_root) {
593         _cleanup_free_ char *fs = NULL;
594         int r = 0;
595
596         assert(path);
597
598         r = cg_get_path(controller, path, NULL, &fs);
599         if (r < 0)
600                 return r;
601
602         errno = 0;
603         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
604                 r = errno ? -errno : -EIO;
605
606         if (delete_root) {
607                 bool is_sticky;
608                 char *p;
609
610                 p = strappend(fs, "/tasks");
611                 if (!p)
612                         return -ENOMEM;
613
614                 is_sticky = file_is_priv_sticky(p) > 0;
615                 free(p);
616
617                 if (!is_sticky)
618                         if (rmdir(fs) < 0 && errno != ENOENT && r == 0)
619                                 return -errno;
620         }
621
622         return r;
623 }
624
625 int cg_delete(const char *controller, const char *path) {
626         _cleanup_free_ char *parent = NULL;
627         int r;
628
629         assert(path);
630
631         r = path_get_parent(path, &parent);
632         if (r < 0)
633                 return r;
634
635         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
636         return r == -ENOENT ? 0 : r;
637 }
638
639 int cg_attach(const char *controller, const char *path, pid_t pid) {
640         _cleanup_free_ char *fs = NULL;
641         char c[DECIMAL_STR_MAX(pid_t) + 2];
642         int r;
643
644         assert(path);
645         assert(pid >= 0);
646
647         r = cg_get_path_and_check(controller, path, "tasks", &fs);
648         if (r < 0)
649                 return r;
650
651         if (pid == 0)
652                 pid = getpid();
653
654         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
655
656         return write_string_file(fs, c);
657 }
658
659 int cg_set_group_access(
660                 const char *controller,
661                 const char *path,
662                 mode_t mode,
663                 uid_t uid,
664                 gid_t gid) {
665
666         _cleanup_free_ char *fs = NULL;
667         int r;
668
669         assert(path);
670
671         if (mode != (mode_t) -1)
672                 mode &= 0777;
673
674         r = cg_get_path(controller, path, NULL, &fs);
675         if (r < 0)
676                 return r;
677
678         return chmod_and_chown(fs, mode, uid, gid);
679 }
680
681 int cg_set_task_access(
682                 const char *controller,
683                 const char *path,
684                 mode_t mode,
685                 uid_t uid,
686                 gid_t gid,
687                 int sticky) {
688
689         _cleanup_free_ char *fs = NULL, *procs = NULL;
690         int r;
691
692         assert(path);
693
694         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1 && sticky < 0)
695                 return 0;
696
697         if (mode != (mode_t) -1)
698                 mode &= 0666;
699
700         r = cg_get_path(controller, path, "tasks", &fs);
701         if (r < 0)
702                 return r;
703
704         if (sticky >= 0 && mode != (mode_t) -1)
705                 /* Both mode and sticky param are passed */
706                 mode |= (sticky ? S_ISVTX : 0);
707         else if ((sticky >= 0 && mode == (mode_t) -1) ||
708                  (mode != (mode_t) -1 && sticky < 0)) {
709                 struct stat st;
710
711                 /* Only one param is passed, hence read the current
712                  * mode from the file itself */
713
714                 r = lstat(fs, &st);
715                 if (r < 0)
716                         return -errno;
717
718                 if (mode == (mode_t) -1)
719                         /* No mode set, we just shall set the sticky bit */
720                         mode = (st.st_mode & ~S_ISVTX) | (sticky ? S_ISVTX : 0);
721                 else
722                         /* Only mode set, leave sticky bit untouched */
723                         mode = (st.st_mode & ~0777) | mode;
724         }
725
726         r = chmod_and_chown(fs, mode, uid, gid);
727         if (r < 0)
728                 return r;
729
730         /* Always keep values for "cgroup.procs" in sync with "tasks" */
731         r = cg_get_path(controller, path, "cgroup.procs", &procs);
732         if (r < 0)
733                 return r;
734
735         return chmod_and_chown(procs, mode, uid, gid);
736 }
737
738 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
739         char fs[sizeof("/proc/") - 1 + DECIMAL_STR_MAX(pid_t) + sizeof("/cgroup")];
740         _cleanup_fclose_ FILE *f = NULL;
741         char line[LINE_MAX];
742         size_t cs;
743
744         assert(path);
745         assert(pid >= 0);
746
747         if (controller && !cg_controller_is_valid(controller, true))
748                 return -EINVAL;
749
750         if (!controller)
751                 controller = SYSTEMD_CGROUP_CONTROLLER;
752
753         if (pid == 0)
754                 pid = getpid();
755
756         sprintf(fs, "/proc/%lu/cgroup", (unsigned long) pid);
757         f = fopen(fs, "re");
758         if (!f)
759                 return errno == ENOENT ? -ESRCH : -errno;
760
761         cs = strlen(controller);
762
763         FOREACH_LINE(line, f, return -errno) {
764                 char *l, *p;
765
766                 truncate_nl(line);
767
768                 l = strchr(line, ':');
769                 if (!l)
770                         continue;
771
772                 l++;
773                 if (!strneq(l, controller, cs))
774                         continue;
775
776                 if (l[cs] != ':')
777                         continue;
778
779                 p = strdup(l + cs + 1);
780                 if (!p)
781                         return -ENOMEM;
782
783                 *path = p;
784                 return 0;
785         }
786
787         return -ENOENT;
788 }
789
790 int cg_install_release_agent(const char *controller, const char *agent) {
791         _cleanup_free_ char *fs = NULL, *contents = NULL;
792         char *sc;
793         int r;
794
795         assert(agent);
796
797         r = cg_get_path(controller, NULL, "release_agent", &fs);
798         if (r < 0)
799                 return r;
800
801         r = read_one_line_file(fs, &contents);
802         if (r < 0)
803                 return r;
804
805         sc = strstrip(contents);
806         if (sc[0] == 0) {
807                 r = write_string_file(fs, agent);
808                 if (r < 0)
809                         return r;
810         } else if (!streq(sc, agent))
811                 return -EEXIST;
812
813         free(fs);
814         fs = NULL;
815         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
816         if (r < 0)
817                 return r;
818
819         free(contents);
820         contents = NULL;
821         r = read_one_line_file(fs, &contents);
822         if (r < 0)
823                 return r;
824
825         sc = strstrip(contents);
826         if (streq(sc, "0")) {
827                 r = write_string_file(fs, "1");
828                 if (r < 0)
829                         return r;
830
831                 return 1;
832         }
833
834         if (!streq(sc, "1"))
835                 return -EIO;
836
837         return 0;
838 }
839
840 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
841         _cleanup_fclose_ FILE *f = NULL;
842         pid_t pid = 0, self_pid;
843         bool found = false;
844         int r;
845
846         assert(path);
847
848         r = cg_enumerate_tasks(controller, path, &f);
849         if (r < 0)
850                 return r == -ENOENT ? 1 : r;
851
852         self_pid = getpid();
853
854         while ((r = cg_read_pid(f, &pid)) > 0) {
855
856                 if (ignore_self && pid == self_pid)
857                         continue;
858
859                 found = true;
860                 break;
861         }
862
863         if (r < 0)
864                 return r;
865
866         return !found;
867 }
868
869 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
870         _cleanup_free_ char *controller = NULL, *path = NULL;
871         int r;
872
873         assert(spec);
874
875         r = cg_split_spec(spec, &controller, &path);
876         if (r < 0)
877                 return r;
878
879         return cg_is_empty(controller, path, ignore_self);
880 }
881
882 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
883         _cleanup_closedir_ DIR *d = NULL;
884         char *fn;
885         int r;
886
887         assert(path);
888
889         r = cg_is_empty(controller, path, ignore_self);
890         if (r <= 0)
891                 return r;
892
893         r = cg_enumerate_subgroups(controller, path, &d);
894         if (r < 0)
895                 return r == -ENOENT ? 1 : r;
896
897         while ((r = cg_read_subgroup(d, &fn)) > 0) {
898                 _cleanup_free_ char *p = NULL;
899
900                 p = strjoin(path, "/", fn, NULL);
901                 free(fn);
902                 if (!p)
903                         return -ENOMEM;
904
905                 r = cg_is_empty_recursive(controller, p, ignore_self);
906                 if (r <= 0)
907                         return r;
908         }
909
910         if (r < 0)
911                 return r;
912
913         return 1;
914 }
915
916 int cg_split_spec(const char *spec, char **controller, char **path) {
917         const char *e;
918         char *t = NULL, *u = NULL;
919
920         assert(spec);
921
922         if (*spec == '/') {
923                 if (!path_is_safe(spec))
924                         return -EINVAL;
925
926                 if (path) {
927                         t = strdup(spec);
928                         if (!t)
929                                 return -ENOMEM;
930
931                         *path = t;
932                 }
933
934                 if (controller)
935                         *controller = NULL;
936
937                 return 0;
938         }
939
940         e = strchr(spec, ':');
941         if (!e) {
942                 if (!cg_controller_is_valid(spec, true))
943                         return -EINVAL;
944
945                 if (controller) {
946                         t = strdup(spec);
947                         if (!t)
948                                 return -ENOMEM;
949
950                         *controller = t;
951                 }
952
953                 if (path)
954                         *path = NULL;
955
956                 return 0;
957         }
958
959         t = strndup(spec, e-spec);
960         if (!t)
961                 return -ENOMEM;
962         if (!cg_controller_is_valid(t, true)) {
963                 free(t);
964                 return -EINVAL;
965         }
966
967         u = strdup(e+1);
968         if (!u) {
969                 free(t);
970                 return -ENOMEM;
971         }
972         if (!path_is_safe(u)) {
973                 free(t);
974                 free(u);
975                 return -EINVAL;
976         }
977
978         if (controller)
979                 *controller = t;
980         else
981                 free(t);
982
983         if (path)
984                 *path = u;
985         else
986                 free(u);
987
988         return 0;
989 }
990
991 int cg_join_spec(const char *controller, const char *path, char **spec) {
992         char *s;
993
994         assert(path);
995
996
997         if (!controller)
998                 controller = "systemd";
999         else {
1000                 if (!cg_controller_is_valid(controller, true))
1001                         return -EINVAL;
1002
1003                 controller = normalize_controller(controller);
1004         }
1005
1006         if (!path_is_absolute(path))
1007                 return -EINVAL;
1008
1009         s = strjoin(controller, ":", path, NULL);
1010         if (!s)
1011                 return -ENOMEM;
1012
1013         *spec = s;
1014         return 0;
1015 }
1016
1017 int cg_mangle_path(const char *path, char **result) {
1018         _cleanup_free_ char *c = NULL, *p = NULL;
1019         char *t;
1020         int r;
1021
1022         assert(path);
1023         assert(result);
1024
1025         /* First check if it already is a filesystem path */
1026         if (path_startswith(path, "/sys/fs/cgroup")) {
1027
1028                 t = strdup(path);
1029                 if (!t)
1030                         return -ENOMEM;
1031
1032                 *result = t;
1033                 return 0;
1034         }
1035
1036         /* Otherwise treat it as cg spec */
1037         r = cg_split_spec(path, &c, &p);
1038         if (r < 0)
1039                 return r;
1040
1041         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1042 }
1043
1044 int cg_get_system_path(char **path) {
1045         char *p;
1046         int r;
1047
1048         assert(path);
1049
1050         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1051         if (r < 0) {
1052                 p = strdup("/system");
1053                 if (!p)
1054                         return -ENOMEM;
1055         }
1056
1057         if (endswith(p, "/system"))
1058                 *path = p;
1059         else {
1060                 char *q;
1061
1062                 q = strappend(p, "/system");
1063                 free(p);
1064                 if (!q)
1065                         return -ENOMEM;
1066
1067                 *path = q;
1068         }
1069
1070         return 0;
1071 }
1072
1073 int cg_get_root_path(char **path) {
1074         char *root, *e;
1075         int r;
1076
1077         assert(path);
1078
1079         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &root);
1080         if (r < 0)
1081                 return r;
1082
1083         e = endswith(root, "/system");
1084         if (e == root)
1085                 e[1] = 0;
1086         else if (e)
1087                 *e = 0;
1088
1089         *path = root;
1090         return 0;
1091 }
1092
1093 int cg_get_user_path(char **path) {
1094         _cleanup_free_ char *root = NULL;
1095         char *p;
1096
1097         assert(path);
1098
1099         /* Figure out the place to put user cgroups below. We use the
1100          * same as PID 1 has but with the "/system" suffix replaced by
1101          * "/user" */
1102
1103         if (cg_get_root_path(&root) < 0 || streq(root, "/"))
1104                 p = strdup("/user");
1105         else
1106                 p = strappend(root, "/user");
1107
1108         if (!p)
1109                 return -ENOMEM;
1110
1111         *path = p;
1112         return 0;
1113 }
1114
1115 int cg_get_machine_path(char **path) {
1116         _cleanup_free_ char *root = NULL;
1117         char *p;
1118
1119         assert(path);
1120
1121         if (cg_get_root_path(&root) < 0 || streq(root, "/"))
1122                 p = strdup("/machine");
1123         else
1124                 p = strappend(root, "/machine");
1125
1126         if (!p)
1127                 return -ENOMEM;
1128
1129         *path = p;
1130         return 0;
1131 }
1132
1133 char **cg_shorten_controllers(char **controllers) {
1134         char **f, **t;
1135
1136         if (!controllers)
1137                 return controllers;
1138
1139         for (f = controllers, t = controllers; *f; f++) {
1140                 const char *p;
1141                 int r;
1142
1143                 p = normalize_controller(*f);
1144
1145                 if (streq(p, "systemd")) {
1146                         free(*f);
1147                         continue;
1148                 }
1149
1150                 if (!cg_controller_is_valid(p, true)) {
1151                         log_warning("Controller %s is not valid, removing from controllers list.", p);
1152                         free(*f);
1153                         continue;
1154                 }
1155
1156                 r = check_hierarchy(p);
1157                 if (r < 0) {
1158                         log_debug("Controller %s is not available, removing from controllers list.", p);
1159                         free(*f);
1160                         continue;
1161                 }
1162
1163                 *(t++) = *f;
1164         }
1165
1166         *t = NULL;
1167         return strv_uniq(controllers);
1168 }
1169
1170 int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) {
1171         _cleanup_free_ char *cg_root = NULL;
1172         char *cg_process, *p;
1173         int r;
1174
1175         r = cg_get_root_path(&cg_root);
1176         if (r < 0)
1177                 return r;
1178
1179         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1180         if (r < 0)
1181                 return r;
1182
1183         p = path_startswith(cg_process, cg_root);
1184         if (p)
1185                 p--;
1186         else
1187                 p = cg_process;
1188
1189         if (cgroup) {
1190                 char* c;
1191
1192                 c = strdup(p);
1193                 if (!c) {
1194                         free(cg_process);
1195                         return -ENOMEM;
1196                 }
1197
1198                 *cgroup = c;
1199         }
1200
1201         if (root) {
1202                 cg_process[p-cg_process] = 0;
1203                 *root = cg_process;
1204         } else
1205                 free(cg_process);
1206
1207         return 0;
1208 }
1209
1210 int cg_path_decode_unit(const char *cgroup, char **unit){
1211         _cleanup_free_ char *unescaped = NULL;
1212         char *p, *e, *c, *s, *k;
1213
1214         assert(cgroup);
1215         assert(unit);
1216
1217         e = strchrnul(cgroup, '/');
1218         c = strndupa(cgroup, e - cgroup);
1219         c = cg_unescape(c);
1220
1221         /* Could this be a valid unit name? */
1222         if (!unit_name_is_valid(c, true))
1223                 return -EINVAL;
1224
1225         if (!unit_name_is_template(c))
1226                 s = strdup(c);
1227         else {
1228                 if (*e != '/')
1229                         return -EINVAL;
1230
1231                 e += strspn(e, "/");
1232
1233                 p = strchrnul(e, '/');
1234                 k = strndupa(e, p - e);
1235                 k = cg_unescape(k);
1236
1237                 if (!unit_name_is_valid(k, false))
1238                         return -EINVAL;
1239
1240                 s = strdup(k);
1241         }
1242
1243         if (!s)
1244                 return -ENOMEM;
1245
1246         *unit = s;
1247         return 0;
1248 }
1249
1250 int cg_path_get_unit(const char *path, char **unit) {
1251         const char *e;
1252
1253         assert(path);
1254         assert(unit);
1255
1256         e = path_startswith(path, "/system/");
1257         if (!e)
1258                 return -ENOENT;
1259
1260         return cg_path_decode_unit(e, unit);
1261 }
1262
1263 int cg_pid_get_unit(pid_t pid, char **unit) {
1264         _cleanup_free_ char *cgroup = NULL;
1265         int r;
1266
1267         assert(unit);
1268
1269         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1270         if (r < 0)
1271                 return r;
1272
1273         return cg_path_get_unit(cgroup, unit);
1274 }
1275
1276 static const char *skip_label(const char *e) {
1277         assert(e);
1278
1279         e = strchr(e, '/');
1280         if (!e)
1281                 return NULL;
1282
1283         e += strspn(e, "/");
1284         return e;
1285 }
1286
1287 int cg_path_get_user_unit(const char *path, char **unit) {
1288         const char *e;
1289
1290         assert(path);
1291         assert(unit);
1292
1293         /* We always have to parse the path from the beginning as unit
1294          * cgroups might have arbitrary child cgroups and we shouldn't get
1295          * confused by those */
1296
1297         e = path_startswith(path, "/user/");
1298         if (!e)
1299                 return -ENOENT;
1300
1301         /* Skip the user name */
1302         e = skip_label(e);
1303         if (!e)
1304                 return -ENOENT;
1305
1306         /* Skip the session ID */
1307         e = skip_label(e);
1308         if (!e)
1309                 return -ENOENT;
1310
1311         /* Skip the systemd cgroup */
1312         e = skip_label(e);
1313         if (!e)
1314                 return -ENOENT;
1315
1316         return cg_path_decode_unit(e, unit);
1317 }
1318
1319 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1320         _cleanup_free_ char *cgroup = NULL;
1321         int r;
1322
1323         assert(unit);
1324
1325         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1326         if (r < 0)
1327                 return r;
1328
1329         return cg_path_get_user_unit(cgroup, unit);
1330 }
1331
1332 int cg_path_get_machine_name(const char *path, char **machine) {
1333         const char *e, *n;
1334         char *s, *r;
1335
1336         assert(path);
1337         assert(machine);
1338
1339         e = path_startswith(path, "/machine/");
1340         if (!e)
1341                 return -ENOENT;
1342
1343         n = strchrnul(e, '/');
1344         if (e == n)
1345                 return -ENOENT;
1346
1347         s = strndupa(e, n - e);
1348
1349         r = strdup(cg_unescape(s));
1350         if (!r)
1351                 return -ENOMEM;
1352
1353         *machine = r;
1354         return 0;
1355 }
1356
1357 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1358         _cleanup_free_ char *cgroup = NULL;
1359         int r;
1360
1361         assert(machine);
1362
1363         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1364         if (r < 0)
1365                 return r;
1366
1367         return cg_path_get_machine_name(cgroup, machine);
1368 }
1369
1370 int cg_path_get_session(const char *path, char **session) {
1371         const char *e, *n;
1372         char *s;
1373
1374         assert(path);
1375         assert(session);
1376
1377         e = path_startswith(path, "/user/");
1378         if (!e)
1379                 return -ENOENT;
1380
1381         /* Skip the user name */
1382         e = skip_label(e);
1383         if (!e)
1384                 return -ENOENT;
1385
1386         n = strchrnul(e, '/');
1387         if (n - e < 8)
1388                 return -ENOENT;
1389         if (memcmp(n - 8, ".session", 8) != 0)
1390                 return -ENOENT;
1391
1392         s = strndup(e, n - e - 8);
1393         if (!s)
1394                 return -ENOMEM;
1395
1396         *session = s;
1397         return 0;
1398 }
1399
1400 int cg_pid_get_session(pid_t pid, char **session) {
1401         _cleanup_free_ char *cgroup = NULL;
1402         int r;
1403
1404         assert(session);
1405
1406         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1407         if (r < 0)
1408                 return r;
1409
1410         return cg_path_get_session(cgroup, session);
1411 }
1412
1413 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1414         const char *e, *n;
1415         char *s;
1416
1417         assert(path);
1418         assert(uid);
1419
1420         e = path_startswith(path, "/user/");
1421         if (!e)
1422                 return -ENOENT;
1423
1424         n = strchrnul(e, '/');
1425         if (n - e < 5)
1426                 return -ENOENT;
1427         if (memcmp(n - 5, ".user", 5) != 0)
1428                 return -ENOENT;
1429
1430         s = strndupa(e, n - e - 5);
1431         if (!s)
1432                 return -ENOMEM;
1433
1434         return parse_uid(s, uid);
1435 }
1436
1437 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1438         _cleanup_free_ char *cgroup = NULL;
1439         int r;
1440
1441         assert(uid);
1442
1443         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1444         if (r < 0)
1445                 return r;
1446
1447         return cg_path_get_owner_uid(cgroup, uid);
1448 }
1449
1450 int cg_controller_from_attr(const char *attr, char **controller) {
1451         const char *dot;
1452         char *c;
1453
1454         assert(attr);
1455         assert(controller);
1456
1457         if (!filename_is_safe(attr))
1458                 return -EINVAL;
1459
1460         dot = strchr(attr, '.');
1461         if (!dot) {
1462                 *controller = NULL;
1463                 return 0;
1464         }
1465
1466         c = strndup(attr, dot - attr);
1467         if (!c)
1468                 return -ENOMEM;
1469
1470         if (!cg_controller_is_valid(c, false)) {
1471                 free(c);
1472                 return -EINVAL;
1473         }
1474
1475         *controller = c;
1476         return 1;
1477 }
1478
1479 char *cg_escape(const char *p) {
1480         bool need_prefix = false;
1481
1482         /* This implements very minimal escaping for names to be used
1483          * as file names in the cgroup tree: any name which might
1484          * conflict with a kernel name or is prefixed with '_' is
1485          * prefixed with a '_'. That way, when reading cgroup names it
1486          * is sufficient to remove a single prefixing underscore if
1487          * there is one. */
1488
1489         /* The return value of this function (unlike cg_unescape())
1490          * needs free()! */
1491
1492         if (p[0] == '_' || streq(p, "notify_on_release") || streq(p, "release_agent") || streq(p, "tasks"))
1493                 need_prefix = true;
1494         else {
1495                 const char *dot;
1496
1497                 dot = strrchr(p, '.');
1498                 if (dot) {
1499
1500                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1501                                 need_prefix = true;
1502                         else {
1503                                 char *n;
1504
1505                                 n = strndupa(p, dot - p);
1506
1507                                 if (check_hierarchy(n) >= 0)
1508                                         need_prefix = true;
1509                         }
1510                 }
1511         }
1512
1513         if (need_prefix)
1514                 return strappend("_", p);
1515         else
1516                 return strdup(p);
1517 }
1518
1519 char *cg_unescape(const char *p) {
1520         assert(p);
1521
1522         /* The return value of this function (unlike cg_escape())
1523          * doesn't need free()! */
1524
1525         if (p[0] == '_')
1526                 return (char*) p+1;
1527
1528         return (char*) p;
1529 }
1530
1531 #define CONTROLLER_VALID                        \
1532         "0123456789"                            \
1533         "abcdefghijklmnopqrstuvwxyz"            \
1534         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"            \
1535         "_"
1536
1537 bool cg_controller_is_valid(const char *p, bool allow_named) {
1538         const char *t, *s;
1539
1540         if (!p)
1541                 return false;
1542
1543         if (allow_named) {
1544                 s = startswith(p, "name=");
1545                 if (s)
1546                         p = s;
1547         }
1548
1549         if (*p == 0 || *p == '_')
1550                 return false;
1551
1552         for (t = p; *t; t++)
1553                 if (!strchr(CONTROLLER_VALID, *t))
1554                         return false;
1555
1556         if (t - p > FILENAME_MAX)
1557                 return false;
1558
1559         return true;
1560 }