chiark / gitweb /
Verify validity of session name when received from outside
[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 #include "special.h"
42
43 int cg_enumerate_processes(const char *controller, const char *path, FILE **_f) {
44         _cleanup_free_ char *fs = NULL;
45         FILE *f;
46         int r;
47
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         if (!f)
56                 return -errno;
57
58         *_f = f;
59         return 0;
60 }
61
62 int cg_read_pid(FILE *f, pid_t *_pid) {
63         unsigned long ul;
64
65         /* Note that the cgroup.procs might contain duplicates! See
66          * cgroups.txt for details. */
67
68         assert(f);
69         assert(_pid);
70
71         errno = 0;
72         if (fscanf(f, "%lu", &ul) != 1) {
73
74                 if (feof(f))
75                         return 0;
76
77                 return errno ? -errno : -EIO;
78         }
79
80         if (ul <= 0)
81                 return -EIO;
82
83         *_pid = (pid_t) ul;
84         return 1;
85 }
86
87 int cg_enumerate_subgroups(const char *controller, const char *path, DIR **_d) {
88         _cleanup_free_ char *fs = NULL;
89         int r;
90         DIR *d;
91
92         assert(_d);
93
94         /* This is not recursive! */
95
96         r = cg_get_path(controller, path, NULL, &fs);
97         if (r < 0)
98                 return r;
99
100         d = opendir(fs);
101         if (!d)
102                 return -errno;
103
104         *_d = d;
105         return 0;
106 }
107
108 int cg_read_subgroup(DIR *d, char **fn) {
109         struct dirent *de;
110
111         assert(d);
112         assert(fn);
113
114         FOREACH_DIRENT(de, d, return -errno) {
115                 char *b;
116
117                 if (de->d_type != DT_DIR)
118                         continue;
119
120                 if (streq(de->d_name, ".") ||
121                     streq(de->d_name, ".."))
122                         continue;
123
124                 b = strdup(de->d_name);
125                 if (!b)
126                         return -ENOMEM;
127
128                 *fn = b;
129                 return 1;
130         }
131
132         return 0;
133 }
134
135 int cg_rmdir(const char *controller, const char *path) {
136         _cleanup_free_ char *p = NULL;
137         int r;
138
139         r = cg_get_path(controller, path, NULL, &p);
140         if (r < 0)
141                 return r;
142
143         r = rmdir(p);
144         if (r < 0 && errno != ENOENT)
145                 return -errno;
146
147         return 0;
148 }
149
150 int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
151         _cleanup_set_free_ Set *allocated_set = NULL;
152         bool done = false;
153         int r, ret = 0;
154         pid_t my_pid;
155
156         assert(sig >= 0);
157
158         /* This goes through the tasks list and kills them all. This
159          * is repeated until no further processes are added to the
160          * tasks list, to properly handle forking processes */
161
162         if (!s) {
163                 s = allocated_set = set_new(trivial_hash_func, trivial_compare_func);
164                 if (!s)
165                         return -ENOMEM;
166         }
167
168         my_pid = getpid();
169
170         do {
171                 _cleanup_fclose_ FILE *f = NULL;
172                 pid_t pid = 0;
173                 done = true;
174
175                 r = cg_enumerate_processes(controller, path, &f);
176                 if (r < 0) {
177                         if (ret >= 0 && r != -ENOENT)
178                                 return r;
179
180                         return ret;
181                 }
182
183                 while ((r = cg_read_pid(f, &pid)) > 0) {
184
185                         if (ignore_self && pid == my_pid)
186                                 continue;
187
188                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
189                                 continue;
190
191                         /* If we haven't killed this process yet, kill
192                          * it */
193                         if (kill(pid, sig) < 0) {
194                                 if (ret >= 0 && errno != ESRCH)
195                                         ret = -errno;
196                         } else if (ret == 0) {
197
198                                 if (sigcont)
199                                         kill(pid, SIGCONT);
200
201                                 ret = 1;
202                         }
203
204                         done = false;
205
206                         r = set_put(s, LONG_TO_PTR(pid));
207                         if (r < 0) {
208                                 if (ret >= 0)
209                                         return r;
210
211                                 return ret;
212                         }
213                 }
214
215                 if (r < 0) {
216                         if (ret >= 0)
217                                 return r;
218
219                         return ret;
220                 }
221
222                 /* To avoid racing against processes which fork
223                  * quicker than we can kill them we repeat this until
224                  * no new pids need to be killed. */
225
226         } while (!done);
227
228         return ret;
229 }
230
231 int cg_kill_recursive(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, bool rem, Set *s) {
232         _cleanup_set_free_ Set *allocated_set = NULL;
233         _cleanup_closedir_ DIR *d = NULL;
234         int r, ret = 0;
235         char *fn;
236
237         assert(path);
238         assert(sig >= 0);
239
240         if (!s) {
241                 s = allocated_set = set_new(trivial_hash_func, trivial_compare_func);
242                 if (!s)
243                         return -ENOMEM;
244         }
245
246         ret = cg_kill(controller, path, sig, sigcont, ignore_self, s);
247
248         r = cg_enumerate_subgroups(controller, path, &d);
249         if (r < 0) {
250                 if (ret >= 0 && r != -ENOENT)
251                         return r;
252
253                 return ret;
254         }
255
256         while ((r = cg_read_subgroup(d, &fn)) > 0) {
257                 _cleanup_free_ char *p = NULL;
258
259                 p = strjoin(path, "/", fn, NULL);
260                 free(fn);
261                 if (!p)
262                         return -ENOMEM;
263
264                 r = cg_kill_recursive(controller, p, sig, sigcont, ignore_self, rem, s);
265                 if (ret >= 0 && r != 0)
266                         ret = r;
267         }
268
269         if (ret >= 0 && r < 0)
270                 ret = r;
271
272         if (rem) {
273                 r = cg_rmdir(controller, path);
274                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
275                         return r;
276         }
277
278         return ret;
279 }
280
281 int cg_kill_recursive_and_wait(const char *controller, const char *path, bool rem) {
282         unsigned i;
283
284         assert(path);
285
286         /* This safely kills all processes; first it sends a SIGTERM,
287          * then checks 8 times after 200ms whether the group is now
288          * empty, then kills everything that is left with SIGKILL and
289          * finally checks 5 times after 200ms each whether the group
290          * is finally empty. */
291
292         for (i = 0; i < 15; i++) {
293                 int sig, r;
294
295                 if (i <= 0)
296                         sig = SIGTERM;
297                 else if (i == 9)
298                         sig = SIGKILL;
299                 else
300                         sig = 0;
301
302                 r = cg_kill_recursive(controller, path, sig, true, true, rem, NULL);
303                 if (r <= 0)
304                         return r;
305
306                 usleep(200 * USEC_PER_MSEC);
307         }
308
309         return 0;
310 }
311
312 int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
313         bool done = false;
314         _cleanup_set_free_ Set *s = NULL;
315         int r, ret = 0;
316         pid_t my_pid;
317
318         assert(cfrom);
319         assert(pfrom);
320         assert(cto);
321         assert(pto);
322
323         s = set_new(trivial_hash_func, trivial_compare_func);
324         if (!s)
325                 return -ENOMEM;
326
327         my_pid = getpid();
328
329         do {
330                 _cleanup_fclose_ FILE *f = NULL;
331                 pid_t pid = 0;
332                 done = true;
333
334                 r = cg_enumerate_processes(cfrom, pfrom, &f);
335                 if (r < 0) {
336                         if (ret >= 0 && r != -ENOENT)
337                                 return r;
338
339                         return ret;
340                 }
341
342                 while ((r = cg_read_pid(f, &pid)) > 0) {
343
344                         /* This might do weird stuff if we aren't a
345                          * single-threaded program. However, we
346                          * luckily know we are not */
347                         if (ignore_self && pid == my_pid)
348                                 continue;
349
350                         if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
351                                 continue;
352
353                         r = cg_attach(cto, pto, pid);
354                         if (r < 0) {
355                                 if (ret >= 0 && r != -ESRCH)
356                                         ret = r;
357                         } else if (ret == 0)
358                                 ret = 1;
359
360                         done = false;
361
362                         r = set_put(s, LONG_TO_PTR(pid));
363                         if (r < 0) {
364                                 if (ret >= 0)
365                                         return r;
366
367                                 return ret;
368                         }
369                 }
370
371                 if (r < 0) {
372                         if (ret >= 0)
373                                 return r;
374
375                         return ret;
376                 }
377         } while (!done);
378
379         return ret;
380 }
381
382 int cg_migrate_recursive(
383                 const char *cfrom,
384                 const char *pfrom,
385                 const char *cto,
386                 const char *pto,
387                 bool ignore_self,
388                 bool rem) {
389
390         _cleanup_closedir_ DIR *d = NULL;
391         int r, ret = 0;
392         char *fn;
393
394         assert(cfrom);
395         assert(pfrom);
396         assert(cto);
397         assert(pto);
398
399         ret = cg_migrate(cfrom, pfrom, cto, pto, ignore_self);
400
401         r = cg_enumerate_subgroups(cfrom, pfrom, &d);
402         if (r < 0) {
403                 if (ret >= 0 && r != -ENOENT)
404                         return r;
405
406                 return ret;
407         }
408
409         while ((r = cg_read_subgroup(d, &fn)) > 0) {
410                 _cleanup_free_ char *p = NULL;
411
412                 p = strjoin(pfrom, "/", fn, NULL);
413                 free(fn);
414                 if (!p) {
415                         if (ret >= 0)
416                                 return -ENOMEM;
417
418                         return ret;
419                 }
420
421                 r = cg_migrate_recursive(cfrom, p, cto, pto, ignore_self, rem);
422                 if (r != 0 && ret >= 0)
423                         ret = r;
424         }
425
426         if (r < 0 && ret >= 0)
427                 ret = r;
428
429         if (rem) {
430                 r = cg_rmdir(cfrom, pfrom);
431                 if (r < 0 && ret >= 0 && r != -ENOENT && r != -EBUSY)
432                         return r;
433         }
434
435         return ret;
436 }
437
438 static const char *normalize_controller(const char *controller) {
439
440         assert(controller);
441
442         if (streq(controller, SYSTEMD_CGROUP_CONTROLLER))
443                 return "systemd";
444         else if (startswith(controller, "name="))
445                 return controller + 5;
446         else
447                 return controller;
448 }
449
450 static int join_path(const char *controller, const char *path, const char *suffix, char **fs) {
451         char *t = NULL;
452
453         if (!isempty(controller)) {
454                 if (!isempty(path) && !isempty(suffix))
455                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, "/", suffix, NULL);
456                 else if (!isempty(path))
457                         t = strjoin("/sys/fs/cgroup/", controller, "/", path, NULL);
458                 else if (!isempty(suffix))
459                         t = strjoin("/sys/fs/cgroup/", controller, "/", suffix, NULL);
460                 else
461                         t = strappend("/sys/fs/cgroup/", controller);
462         } else {
463                 if (!isempty(path) && !isempty(suffix))
464                         t = strjoin(path, "/", suffix, NULL);
465                 else if (!isempty(path))
466                         t = strdup(path);
467                 else
468                         return -EINVAL;
469         }
470
471         if (!t)
472                 return -ENOMEM;
473
474         path_kill_slashes(t);
475
476         *fs = t;
477         return 0;
478 }
479
480 int cg_get_path(const char *controller, const char *path, const char *suffix, char **fs) {
481         const char *p;
482         static __thread bool good = false;
483
484         assert(fs);
485
486         if (controller && !cg_controller_is_valid(controller, true))
487                 return -EINVAL;
488
489         if (_unlikely_(!good)) {
490                 int r;
491
492                 r = path_is_mount_point("/sys/fs/cgroup", false);
493                 if (r <= 0)
494                         return r < 0 ? r : -ENOENT;
495
496                 /* Cache this to save a few stat()s */
497                 good = true;
498         }
499
500         p = controller ? normalize_controller(controller) : NULL;
501
502         return join_path(p, path, suffix, fs);
503 }
504
505 static int check_hierarchy(const char *p) {
506         char *cc;
507
508         assert(p);
509
510         /* Check if this controller actually really exists */
511         cc = alloca(sizeof("/sys/fs/cgroup/") + strlen(p));
512         strcpy(stpcpy(cc, "/sys/fs/cgroup/"), p);
513         if (access(cc, F_OK) < 0)
514                 return -errno;
515
516         return 0;
517 }
518
519 int cg_get_path_and_check(const char *controller, const char *path, const char *suffix, char **fs) {
520         const char *p;
521         int r;
522
523         assert(fs);
524
525         if (!cg_controller_is_valid(controller, true))
526                 return -EINVAL;
527
528         /* Normalize the controller syntax */
529         p = normalize_controller(controller);
530
531         /* Check if this controller actually really exists */
532         r = check_hierarchy(p);
533         if (r < 0)
534                 return r;
535
536         return join_path(p, path, suffix, fs);
537 }
538
539 static int trim_cb(const char *path, const struct stat *sb, int typeflag, struct FTW *ftwbuf) {
540         assert(path);
541         assert(sb);
542         assert(ftwbuf);
543
544         if (typeflag != FTW_DP)
545                 return 0;
546
547         if (ftwbuf->level < 1)
548                 return 0;
549
550         rmdir(path);
551         return 0;
552 }
553
554 int cg_trim(const char *controller, const char *path, bool delete_root) {
555         _cleanup_free_ char *fs = NULL;
556         int r = 0;
557
558         assert(path);
559
560         r = cg_get_path(controller, path, NULL, &fs);
561         if (r < 0)
562                 return r;
563
564         errno = 0;
565         if (nftw(fs, trim_cb, 64, FTW_DEPTH|FTW_MOUNT|FTW_PHYS) != 0)
566                 r = errno ? -errno : -EIO;
567
568         if (delete_root) {
569                 if (rmdir(fs) < 0 && errno != ENOENT)
570                         return -errno;
571         }
572
573         return r;
574 }
575
576 int cg_delete(const char *controller, const char *path) {
577         _cleanup_free_ char *parent = NULL;
578         int r;
579
580         assert(path);
581
582         r = path_get_parent(path, &parent);
583         if (r < 0)
584                 return r;
585
586         r = cg_migrate_recursive(controller, path, controller, parent, false, true);
587         return r == -ENOENT ? 0 : r;
588 }
589
590 int cg_attach(const char *controller, const char *path, pid_t pid) {
591         _cleanup_free_ char *fs = NULL;
592         char c[DECIMAL_STR_MAX(pid_t) + 2];
593         int r;
594
595         assert(path);
596         assert(pid >= 0);
597
598         r = cg_get_path_and_check(controller, path, "cgroup.procs", &fs);
599         if (r < 0)
600                 return r;
601
602         if (pid == 0)
603                 pid = getpid();
604
605         snprintf(c, sizeof(c), "%lu\n", (unsigned long) pid);
606
607         return write_string_file(fs, c);
608 }
609
610 int cg_set_group_access(
611                 const char *controller,
612                 const char *path,
613                 mode_t mode,
614                 uid_t uid,
615                 gid_t gid) {
616
617         _cleanup_free_ char *fs = NULL;
618         int r;
619
620         assert(path);
621
622         if (mode != (mode_t) -1)
623                 mode &= 0777;
624
625         r = cg_get_path(controller, path, NULL, &fs);
626         if (r < 0)
627                 return r;
628
629         return chmod_and_chown(fs, mode, uid, gid);
630 }
631
632 int cg_set_task_access(
633                 const char *controller,
634                 const char *path,
635                 mode_t mode,
636                 uid_t uid,
637                 gid_t gid) {
638
639         _cleanup_free_ char *fs = NULL, *procs = NULL;
640         int r;
641
642         assert(path);
643
644         if (mode == (mode_t) -1 && uid == (uid_t) -1 && gid == (gid_t) -1)
645                 return 0;
646
647         if (mode != (mode_t) -1)
648                 mode &= 0666;
649
650         r = cg_get_path(controller, path, "cgroup.procs", &fs);
651         if (r < 0)
652                 return r;
653
654         r = chmod_and_chown(fs, mode, uid, gid);
655         if (r < 0)
656                 return r;
657
658         /* Compatibility, Always keep values for "tasks" in sync with
659          * "cgroup.procs" */
660         r = cg_get_path(controller, path, "tasks", &procs);
661         if (r < 0)
662                 return r;
663
664         return chmod_and_chown(procs, mode, uid, gid);
665 }
666
667 int cg_pid_get_path(const char *controller, pid_t pid, char **path) {
668         _cleanup_fclose_ FILE *f = NULL;
669         char line[LINE_MAX];
670         const char *fs;
671         size_t cs;
672
673         assert(path);
674         assert(pid >= 0);
675
676         if (controller) {
677                 if (!cg_controller_is_valid(controller, true))
678                         return -EINVAL;
679
680                 controller = normalize_controller(controller);
681         } else
682                 controller = SYSTEMD_CGROUP_CONTROLLER;
683
684         if (pid == 0)
685                 fs = "/proc/self/cgroup";
686         else
687                 fs = procfs_file_alloca(pid, "cgroup");
688
689         f = fopen(fs, "re");
690         if (!f)
691                 return errno == ENOENT ? -ESRCH : -errno;
692
693         cs = strlen(controller);
694
695         FOREACH_LINE(line, f, return -errno) {
696                 char *l, *p, *w, *e;
697                 size_t k;
698                 char *state;
699                 bool found = false;
700
701                 truncate_nl(line);
702
703                 l = strchr(line, ':');
704                 if (!l)
705                         continue;
706
707                 l++;
708                 e = strchr(l, ':');
709                 if (!e)
710                         continue;
711
712                 *e = 0;
713
714                 FOREACH_WORD_SEPARATOR(w, k, l, ",", state) {
715
716                         if (k == cs && memcmp(w, controller, cs) == 0) {
717                                 found = true;
718                                 break;
719                         }
720
721                         if (k == 5 + cs &&
722                             memcmp(w, "name=", 5) == 0 &&
723                             memcmp(w+5, controller, cs) == 0) {
724                                 found = true;
725                                 break;
726                         }
727                 }
728
729                 if (!found)
730                         continue;
731
732                 p = strdup(e + 1);
733                 if (!p)
734                         return -ENOMEM;
735
736                 *path = p;
737                 return 0;
738         }
739
740         return -ENOENT;
741 }
742
743 int cg_install_release_agent(const char *controller, const char *agent) {
744         _cleanup_free_ char *fs = NULL, *contents = NULL;
745         char *sc;
746         int r;
747
748         assert(agent);
749
750         r = cg_get_path(controller, NULL, "release_agent", &fs);
751         if (r < 0)
752                 return r;
753
754         r = read_one_line_file(fs, &contents);
755         if (r < 0)
756                 return r;
757
758         sc = strstrip(contents);
759         if (sc[0] == 0) {
760                 r = write_string_file(fs, agent);
761                 if (r < 0)
762                         return r;
763         } else if (!streq(sc, agent))
764                 return -EEXIST;
765
766         free(fs);
767         fs = NULL;
768         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
769         if (r < 0)
770                 return r;
771
772         free(contents);
773         contents = NULL;
774         r = read_one_line_file(fs, &contents);
775         if (r < 0)
776                 return r;
777
778         sc = strstrip(contents);
779         if (streq(sc, "0")) {
780                 r = write_string_file(fs, "1");
781                 if (r < 0)
782                         return r;
783
784                 return 1;
785         }
786
787         if (!streq(sc, "1"))
788                 return -EIO;
789
790         return 0;
791 }
792
793 int cg_uninstall_release_agent(const char *controller) {
794         _cleanup_free_ char *fs = NULL;
795         int r;
796
797         r = cg_get_path(controller, NULL, "notify_on_release", &fs);
798         if (r < 0)
799                 return r;
800
801         r = write_string_file(fs, "0");
802         if (r < 0)
803                 return r;
804
805         free(fs);
806         fs = NULL;
807
808         r = cg_get_path(controller, NULL, "release_agent", &fs);
809         if (r < 0)
810                 return r;
811
812         r = write_string_file(fs, "");
813         if (r < 0)
814                 return r;
815
816         return 0;
817 }
818
819 int cg_is_empty(const char *controller, const char *path, bool ignore_self) {
820         _cleanup_fclose_ FILE *f = NULL;
821         pid_t pid = 0, self_pid;
822         bool found = false;
823         int r;
824
825         assert(path);
826
827         r = cg_enumerate_processes(controller, path, &f);
828         if (r < 0)
829                 return r == -ENOENT ? 1 : r;
830
831         self_pid = getpid();
832
833         while ((r = cg_read_pid(f, &pid)) > 0) {
834
835                 if (ignore_self && pid == self_pid)
836                         continue;
837
838                 found = true;
839                 break;
840         }
841
842         if (r < 0)
843                 return r;
844
845         return !found;
846 }
847
848 int cg_is_empty_by_spec(const char *spec, bool ignore_self) {
849         _cleanup_free_ char *controller = NULL, *path = NULL;
850         int r;
851
852         assert(spec);
853
854         r = cg_split_spec(spec, &controller, &path);
855         if (r < 0)
856                 return r;
857
858         return cg_is_empty(controller, path, ignore_self);
859 }
860
861 int cg_is_empty_recursive(const char *controller, const char *path, bool ignore_self) {
862         _cleanup_closedir_ DIR *d = NULL;
863         char *fn;
864         int r;
865
866         assert(path);
867
868         r = cg_is_empty(controller, path, ignore_self);
869         if (r <= 0)
870                 return r;
871
872         r = cg_enumerate_subgroups(controller, path, &d);
873         if (r < 0)
874                 return r == -ENOENT ? 1 : r;
875
876         while ((r = cg_read_subgroup(d, &fn)) > 0) {
877                 _cleanup_free_ char *p = NULL;
878
879                 p = strjoin(path, "/", fn, NULL);
880                 free(fn);
881                 if (!p)
882                         return -ENOMEM;
883
884                 r = cg_is_empty_recursive(controller, p, ignore_self);
885                 if (r <= 0)
886                         return r;
887         }
888
889         if (r < 0)
890                 return r;
891
892         return 1;
893 }
894
895 int cg_split_spec(const char *spec, char **controller, char **path) {
896         const char *e;
897         char *t = NULL, *u = NULL;
898         _cleanup_free_ char *v = NULL;
899
900         assert(spec);
901
902         if (*spec == '/') {
903                 if (!path_is_safe(spec))
904                         return -EINVAL;
905
906                 if (path) {
907                         t = strdup(spec);
908                         if (!t)
909                                 return -ENOMEM;
910
911                         path_kill_slashes(t);
912                         *path = t;
913                 }
914
915                 if (controller)
916                         *controller = NULL;
917
918                 return 0;
919         }
920
921         e = strchr(spec, ':');
922         if (!e) {
923                 if (!cg_controller_is_valid(spec, true))
924                         return -EINVAL;
925
926                 if (controller) {
927                         t = strdup(normalize_controller(spec));
928                         if (!t)
929                                 return -ENOMEM;
930
931                         *controller = t;
932                 }
933
934                 if (path)
935                         *path = NULL;
936
937                 return 0;
938         }
939
940         v = strndup(spec, e-spec);
941         if (!v)
942                 return -ENOMEM;
943         t = strdup(normalize_controller(v));
944         if (!t)
945                 return -ENOMEM;
946         if (!cg_controller_is_valid(t, true)) {
947                 free(t);
948                 return -EINVAL;
949         }
950
951         u = strdup(e+1);
952         if (!u) {
953                 free(t);
954                 return -ENOMEM;
955         }
956         if (!path_is_safe(u) ||
957             !path_is_absolute(u)) {
958                 free(t);
959                 free(u);
960                 return -EINVAL;
961         }
962
963         path_kill_slashes(u);
964
965         if (controller)
966                 *controller = t;
967         else
968                 free(t);
969
970         if (path)
971                 *path = u;
972         else
973                 free(u);
974
975         return 0;
976 }
977
978 int cg_join_spec(const char *controller, const char *path, char **spec) {
979         char *s;
980
981         assert(path);
982
983         if (!controller)
984                 controller = "systemd";
985         else {
986                 if (!cg_controller_is_valid(controller, true))
987                         return -EINVAL;
988
989                 controller = normalize_controller(controller);
990         }
991
992         if (!path_is_absolute(path))
993                 return -EINVAL;
994
995         s = strjoin(controller, ":", path, NULL);
996         if (!s)
997                 return -ENOMEM;
998
999         path_kill_slashes(s + strlen(controller) + 1);
1000
1001         *spec = s;
1002         return 0;
1003 }
1004
1005 int cg_mangle_path(const char *path, char **result) {
1006         _cleanup_free_ char *c = NULL, *p = NULL;
1007         char *t;
1008         int r;
1009
1010         assert(path);
1011         assert(result);
1012
1013         /* First check if it already is a filesystem path */
1014         if (path_startswith(path, "/sys/fs/cgroup")) {
1015
1016                 t = strdup(path);
1017                 if (!t)
1018                         return -ENOMEM;
1019
1020                 path_kill_slashes(t);
1021                 *result = t;
1022                 return 0;
1023         }
1024
1025         /* Otherwise treat it as cg spec */
1026         r = cg_split_spec(path, &c, &p);
1027         if (r < 0)
1028                 return r;
1029
1030         return cg_get_path(c ? c : SYSTEMD_CGROUP_CONTROLLER, p ? p : "/", NULL, result);
1031 }
1032
1033 int cg_get_root_path(char **path) {
1034         char *p, *e;
1035         int r;
1036
1037         assert(path);
1038
1039         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &p);
1040         if (r < 0)
1041                 return r;
1042
1043         e = endswith(p, "/" SPECIAL_SYSTEM_SLICE);
1044         if (e)
1045                 *e = 0;
1046
1047         *path = p;
1048         return 0;
1049 }
1050
1051 char **cg_shorten_controllers(char **controllers) {
1052         char **f, **t;
1053
1054         if (!controllers)
1055                 return controllers;
1056
1057         for (f = controllers, t = controllers; *f; f++) {
1058                 const char *p;
1059                 int r;
1060
1061                 p = normalize_controller(*f);
1062
1063                 if (streq(p, "systemd")) {
1064                         free(*f);
1065                         continue;
1066                 }
1067
1068                 if (!cg_controller_is_valid(p, true)) {
1069                         log_warning("Controller %s is not valid, removing from controllers list.", p);
1070                         free(*f);
1071                         continue;
1072                 }
1073
1074                 r = check_hierarchy(p);
1075                 if (r < 0) {
1076                         log_debug("Controller %s is not available, removing from controllers list.", p);
1077                         free(*f);
1078                         continue;
1079                 }
1080
1081                 *(t++) = *f;
1082         }
1083
1084         *t = NULL;
1085         return strv_uniq(controllers);
1086 }
1087
1088 int cg_pid_get_path_shifted(pid_t pid, char **root, char **cgroup) {
1089         _cleanup_free_ char *cg_root = NULL;
1090         char *cg_process, *p;
1091         int r;
1092
1093         r = cg_get_root_path(&cg_root);
1094         if (r < 0)
1095                 return r;
1096
1097         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cg_process);
1098         if (r < 0)
1099                 return r;
1100
1101         p = path_startswith(cg_process, cg_root);
1102         if (p)
1103                 p--;
1104         else
1105                 p = cg_process;
1106
1107         if (cgroup) {
1108                 char* c;
1109
1110                 c = strdup(p);
1111                 if (!c) {
1112                         free(cg_process);
1113                         return -ENOMEM;
1114                 }
1115
1116                 *cgroup = c;
1117         }
1118
1119         if (root) {
1120                 cg_process[p-cg_process] = 0;
1121                 *root = cg_process;
1122         } else
1123                 free(cg_process);
1124
1125         return 0;
1126 }
1127
1128 int cg_path_decode_unit(const char *cgroup, char **unit){
1129         char *e, *c, *s;
1130
1131         assert(cgroup);
1132         assert(unit);
1133
1134         e = strchrnul(cgroup, '/');
1135         c = strndupa(cgroup, e - cgroup);
1136         c = cg_unescape(c);
1137
1138         if (!unit_name_is_valid(c, false))
1139                 return -EINVAL;
1140
1141         s = strdup(c);
1142         if (!s)
1143                 return -ENOMEM;
1144
1145         *unit = s;
1146         return 0;
1147 }
1148
1149 static const char *skip_slices(const char *p) {
1150         /* Skips over all slice assignments */
1151
1152         for (;;) {
1153                 size_t n;
1154
1155                 p += strspn(p, "/");
1156
1157                 n = strcspn(p, "/");
1158                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0)
1159                         return p;
1160
1161                 p += n;
1162         }
1163 }
1164
1165 int cg_path_get_unit(const char *path, char **unit) {
1166         const char *e;
1167
1168         assert(path);
1169         assert(unit);
1170
1171         e = skip_slices(path);
1172
1173         return cg_path_decode_unit(e, unit);
1174 }
1175
1176 int cg_pid_get_unit(pid_t pid, char **unit) {
1177         _cleanup_free_ char *cgroup = NULL;
1178         int r;
1179
1180         assert(unit);
1181
1182         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1183         if (r < 0)
1184                 return r;
1185
1186         return cg_path_get_unit(cgroup, unit);
1187 }
1188
1189 static const char *skip_session(const char *p) {
1190         size_t n;
1191
1192         assert(p);
1193
1194         p += strspn(p, "/");
1195
1196         n = strcspn(p, "/");
1197         if (n <= 12 || memcmp(p, "session-", 8) != 0 || memcmp(p + n - 6, ".scope", 6) != 0)
1198                 return NULL;
1199
1200         p += n;
1201         p += strspn(p, "/");
1202
1203         return p;
1204 }
1205
1206 int cg_path_get_user_unit(const char *path, char **unit) {
1207         const char *e;
1208
1209         assert(path);
1210         assert(unit);
1211
1212         /* We always have to parse the path from the beginning as unit
1213          * cgroups might have arbitrary child cgroups and we shouldn't get
1214          * confused by those */
1215
1216         /* Skip slices, if there are any */
1217         e = skip_slices(path);
1218
1219         /* Skip the session scope, require that there is one */
1220         e = skip_session(e);
1221         if (!e)
1222                 return -ENOENT;
1223
1224         /* And skip more slices */
1225         e = skip_slices(e);
1226
1227         return cg_path_decode_unit(e, unit);
1228 }
1229
1230 int cg_pid_get_user_unit(pid_t pid, char **unit) {
1231         _cleanup_free_ char *cgroup = NULL;
1232         int r;
1233
1234         assert(unit);
1235
1236         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1237         if (r < 0)
1238                 return r;
1239
1240         return cg_path_get_user_unit(cgroup, unit);
1241 }
1242
1243 int cg_path_get_machine_name(const char *path, char **machine) {
1244         const char *e, *n, *x;
1245         char *s, *r;
1246         size_t l;
1247
1248         assert(path);
1249         assert(machine);
1250
1251         /* Skip slices, if there are any */
1252         e = skip_slices(path);
1253
1254         n = strchrnul(e, '/');
1255         if (e == n)
1256                 return -ENOENT;
1257
1258         s = strndupa(e, n - e);
1259         s = cg_unescape(s);
1260
1261         x = startswith(s, "machine-");
1262         if (!x)
1263                 return -ENOENT;
1264         if (!endswith(x, ".scope"))
1265                 return -ENOENT;
1266
1267         l = strlen(x);
1268         if (l <= 6)
1269                 return -ENOENT;
1270
1271         r = strndup(x, l - 6);
1272         if (!r)
1273                 return -ENOMEM;
1274
1275         *machine = r;
1276         return 0;
1277 }
1278
1279 int cg_pid_get_machine_name(pid_t pid, char **machine) {
1280         _cleanup_free_ char *cgroup = NULL;
1281         int r;
1282
1283         assert(machine);
1284
1285         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1286         if (r < 0)
1287                 return r;
1288
1289         return cg_path_get_machine_name(cgroup, machine);
1290 }
1291
1292 int cg_path_get_session(const char *path, char **session) {
1293         const char *e, *n, *x;
1294         char *s, *r;
1295         size_t l;
1296
1297         assert(path);
1298         assert(session);
1299
1300         /* Skip slices, if there are any */
1301         e = skip_slices(path);
1302
1303         n = strchrnul(e, '/');
1304         if (e == n)
1305                 return -ENOENT;
1306
1307         s = strndupa(e, n - e);
1308         s = cg_unescape(s);
1309
1310         x = startswith(s, "session-");
1311         if (!x)
1312                 return -ENOENT;
1313         if (!endswith(x, ".scope"))
1314                 return -ENOENT;
1315
1316         l = strlen(x);
1317         if (l <= 6)
1318                 return -ENOENT;
1319
1320         r = strndup(x, l - 6);
1321         if (!r)
1322                 return -ENOMEM;
1323
1324         *session = r;
1325         return 0;
1326 }
1327
1328 int cg_pid_get_session(pid_t pid, char **session) {
1329         _cleanup_free_ char *cgroup = NULL;
1330         int r;
1331
1332         assert(session);
1333
1334         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1335         if (r < 0)
1336                 return r;
1337
1338         return cg_path_get_session(cgroup, session);
1339 }
1340
1341 int cg_path_get_owner_uid(const char *path, uid_t *uid) {
1342         _cleanup_free_ char *slice = NULL;
1343         const char *e;
1344         char *s;
1345         int r;
1346
1347         assert(path);
1348         assert(uid);
1349
1350         r = cg_path_get_slice(path, &slice);
1351         if (r < 0)
1352                 return r;
1353
1354         e = startswith(slice, "user-");
1355         if (!e)
1356                 return -ENOENT;
1357         if (!endswith(slice, ".slice"))
1358                 return -ENOENT;
1359
1360         s = strndupa(e, strlen(e) - 6);
1361         if (!s)
1362                 return -ENOMEM;
1363
1364         return parse_uid(s, uid);
1365 }
1366
1367 int cg_pid_get_owner_uid(pid_t pid, uid_t *uid) {
1368         _cleanup_free_ char *cgroup = NULL;
1369         int r;
1370
1371         assert(uid);
1372
1373         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1374         if (r < 0)
1375                 return r;
1376
1377         return cg_path_get_owner_uid(cgroup, uid);
1378 }
1379
1380 int cg_path_get_slice(const char *p, char **slice) {
1381         const char *e = NULL;
1382         size_t m = 0;
1383
1384         assert(p);
1385         assert(slice);
1386
1387         for (;;) {
1388                 size_t n;
1389
1390                 p += strspn(p, "/");
1391
1392                 n = strcspn(p, "/");
1393                 if (n <= 6 || memcmp(p + n - 6, ".slice", 6) != 0) {
1394                         char *s;
1395
1396                         if (!e)
1397                                 return -ENOENT;
1398
1399                         s = strndup(e, m);
1400                         if (!s)
1401                                 return -ENOMEM;
1402
1403                         *slice = s;
1404                         return 0;
1405                 }
1406
1407                 e = p;
1408                 m = n;
1409
1410                 p += n;
1411         }
1412 }
1413
1414 int cg_pid_get_slice(pid_t pid, char **slice) {
1415         _cleanup_free_ char *cgroup = NULL;
1416         int r;
1417
1418         assert(slice);
1419
1420         r = cg_pid_get_path_shifted(pid, NULL, &cgroup);
1421         if (r < 0)
1422                 return r;
1423
1424         return cg_path_get_slice(cgroup, slice);
1425 }
1426
1427 int cg_controller_from_attr(const char *attr, char **controller) {
1428         const char *dot;
1429         char *c;
1430
1431         assert(attr);
1432         assert(controller);
1433
1434         if (!filename_is_safe(attr))
1435                 return -EINVAL;
1436
1437         dot = strchr(attr, '.');
1438         if (!dot) {
1439                 *controller = NULL;
1440                 return 0;
1441         }
1442
1443         c = strndup(attr, dot - attr);
1444         if (!c)
1445                 return -ENOMEM;
1446
1447         if (!cg_controller_is_valid(c, false)) {
1448                 free(c);
1449                 return -EINVAL;
1450         }
1451
1452         *controller = c;
1453         return 1;
1454 }
1455
1456 char *cg_escape(const char *p) {
1457         bool need_prefix = false;
1458
1459         /* This implements very minimal escaping for names to be used
1460          * as file names in the cgroup tree: any name which might
1461          * conflict with a kernel name or is prefixed with '_' is
1462          * prefixed with a '_'. That way, when reading cgroup names it
1463          * is sufficient to remove a single prefixing underscore if
1464          * there is one. */
1465
1466         /* The return value of this function (unlike cg_unescape())
1467          * needs free()! */
1468
1469         if (p[0] == 0 ||
1470             p[0] == '_' ||
1471             p[0] == '.' ||
1472             streq(p, "notify_on_release") ||
1473             streq(p, "release_agent") ||
1474             streq(p, "tasks"))
1475                 need_prefix = true;
1476         else {
1477                 const char *dot;
1478
1479                 dot = strrchr(p, '.');
1480                 if (dot) {
1481
1482                         if (dot - p == 6 && memcmp(p, "cgroup", 6) == 0)
1483                                 need_prefix = true;
1484                         else {
1485                                 char *n;
1486
1487                                 n = strndupa(p, dot - p);
1488
1489                                 if (check_hierarchy(n) >= 0)
1490                                         need_prefix = true;
1491                         }
1492                 }
1493         }
1494
1495         if (need_prefix)
1496                 return strappend("_", p);
1497         else
1498                 return strdup(p);
1499 }
1500
1501 char *cg_unescape(const char *p) {
1502         assert(p);
1503
1504         /* The return value of this function (unlike cg_escape())
1505          * doesn't need free()! */
1506
1507         if (p[0] == '_')
1508                 return (char*) p+1;
1509
1510         return (char*) p;
1511 }
1512
1513 #define CONTROLLER_VALID                        \
1514         DIGITS LETTERS                          \
1515         "_"
1516
1517 bool cg_controller_is_valid(const char *p, bool allow_named) {
1518         const char *t, *s;
1519
1520         if (!p)
1521                 return false;
1522
1523         if (allow_named) {
1524                 s = startswith(p, "name=");
1525                 if (s)
1526                         p = s;
1527         }
1528
1529         if (*p == 0 || *p == '_')
1530                 return false;
1531
1532         for (t = p; *t; t++)
1533                 if (!strchr(CONTROLLER_VALID, *t))
1534                         return false;
1535
1536         if (t - p > FILENAME_MAX)
1537                 return false;
1538
1539         return true;
1540 }
1541
1542 int cg_slice_to_path(const char *unit, char **ret) {
1543         _cleanup_free_ char *p = NULL, *s = NULL, *e = NULL;
1544         const char *dash;
1545
1546         assert(unit);
1547         assert(ret);
1548
1549         if (!unit_name_is_valid(unit, false))
1550                 return -EINVAL;
1551
1552         if (!endswith(unit, ".slice"))
1553                 return -EINVAL;
1554
1555         p = unit_name_to_prefix(unit);
1556         if (!p)
1557                 return -ENOMEM;
1558
1559         dash = strchr(p, '-');
1560         while (dash) {
1561                 _cleanup_free_ char *escaped = NULL;
1562                 char n[dash - p + sizeof(".slice")];
1563
1564                 strcpy(stpncpy(n, p, dash - p), ".slice");
1565
1566                 if (!unit_name_is_valid(n, false))
1567                         return -EINVAL;
1568
1569                 escaped = cg_escape(n);
1570                 if (!escaped)
1571                         return -ENOMEM;
1572
1573                 if (!strextend(&s, escaped, "/", NULL))
1574                         return -ENOMEM;
1575
1576                 dash = strchr(dash+1, '-');
1577         }
1578
1579         e = cg_escape(unit);
1580         if (!e)
1581                 return -ENOMEM;
1582
1583         if (!strextend(&s, e, NULL))
1584                 return -ENOMEM;
1585
1586         *ret = s;
1587         s = NULL;
1588
1589         return 0;
1590 }
1591
1592 int cg_set_attribute(const char *controller, const char *path, const char *attribute, const char *value) {
1593         _cleanup_free_ char *p = NULL;
1594         int r;
1595
1596         r = cg_get_path(controller, path, attribute, &p);
1597         if (r < 0)
1598                 return r;
1599
1600         return write_string_file(p, value);
1601 }
1602
1603 static const char mask_names[] =
1604         "cpu\0"
1605         "cpuacct\0"
1606         "blkio\0"
1607         "memory\0"
1608         "devices\0";
1609
1610 int cg_create_with_mask(CGroupControllerMask mask, const char *path) {
1611         CGroupControllerMask bit = 1;
1612         const char *n;
1613         int r;
1614
1615         /* This one will create a cgroup in our private tree, but also
1616          * duplicate it in the trees specified in mask, and remove it
1617          * in all others */
1618
1619         /* First create the cgroup in our own hierarchy. */
1620         r = cg_create(SYSTEMD_CGROUP_CONTROLLER, path);
1621         if (r < 0)
1622                 return r;
1623
1624         /* Then, do the same in the other hierarchies */
1625         NULSTR_FOREACH(n, mask_names) {
1626                 if (bit & mask)
1627                         cg_create(n, path);
1628                 else
1629                         cg_trim(n, path, true);
1630
1631                 bit <<= 1;
1632         }
1633
1634         return r;
1635 }
1636
1637 int cg_attach_with_mask(CGroupControllerMask mask, const char *path, pid_t pid) {
1638         CGroupControllerMask bit = 1;
1639         const char *n;
1640         int r;
1641
1642         r = cg_attach(SYSTEMD_CGROUP_CONTROLLER, path, pid);
1643
1644         NULSTR_FOREACH(n, mask_names) {
1645                 if (bit & mask)
1646                         cg_attach(n, path, pid);
1647                 else {
1648                         char prefix[strlen(path) + 1], *slash;
1649
1650                         /* OK, this one is a bit harder... Now we need
1651                          * to add to the closest parent cgroup we
1652                          * can find */
1653                         strcpy(prefix, path);
1654                         while ((slash = strrchr(prefix, '/'))) {
1655                                 int q;
1656                                 *slash = 0;
1657
1658                                 q = cg_attach(n, prefix, pid);
1659                                 if (q >= 0)
1660                                         break;
1661                         }
1662                 }
1663
1664                 bit <<= 1;
1665         }
1666
1667         return r;
1668 }
1669
1670 int cg_attach_many_with_mask(CGroupControllerMask mask, const char *path, Set* pids) {
1671         Iterator i;
1672         void *pidp;
1673         int r = 0;
1674
1675         SET_FOREACH(pidp, pids, i) {
1676                 pid_t pid = PTR_TO_LONG(pidp);
1677                 int k;
1678
1679                 k = cg_attach_with_mask(mask, path, pid);
1680                 if (k < 0)
1681                         r = k;
1682         }
1683
1684         return r;
1685 }
1686
1687 int cg_migrate_with_mask(CGroupControllerMask mask, const char *from, const char *to) {
1688         CGroupControllerMask bit = 1;
1689         const char *n;
1690         int r;
1691
1692         if (path_equal(from, to))
1693                 return 0;
1694
1695         r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true);
1696
1697         NULSTR_FOREACH(n, mask_names) {
1698                 if (bit & mask)
1699                         cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, to, false, false);
1700                 else {
1701                         char prefix[strlen(to) + 1], *slash;
1702
1703                         strcpy(prefix, to);
1704                         while ((slash = strrchr(prefix, '/'))) {
1705                                 int q;
1706
1707                                 *slash = 0;
1708
1709                                 q = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, to, n, prefix, false, false);
1710                                 if (q >= 0)
1711                                         break;
1712                         }
1713                 }
1714
1715                 bit <<= 1;
1716         }
1717
1718         return r;
1719 }
1720
1721 int cg_trim_with_mask(CGroupControllerMask mask, const char *path, bool delete_root) {
1722         CGroupControllerMask bit = 1;
1723         const char *n;
1724         int r;
1725
1726         r = cg_trim(SYSTEMD_CGROUP_CONTROLLER, path, delete_root);
1727         if (r < 0)
1728                 return r;
1729
1730         NULSTR_FOREACH(n, mask_names) {
1731                 if (bit & mask)
1732                         cg_trim(n, path, delete_root);
1733
1734                 bit <<= 1;
1735         }
1736
1737         return r;
1738 }
1739
1740 CGroupControllerMask cg_mask_supported(void) {
1741         CGroupControllerMask bit = 1, mask = 0;
1742         const char *n;
1743
1744         NULSTR_FOREACH(n, mask_names) {
1745                 if (check_hierarchy(n) >= 0)
1746                         mask |= bit;
1747
1748                 bit <<= 1;
1749         }
1750
1751         return mask;
1752 }