chiark / gitweb /
34ff984df5ad79b2b3c2d8dd05fd065d36ded148
[elogind.git] / src / core / cgroup.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2013 Lennart Poettering
6 ***/
7
8 #include <fcntl.h>
9 #include <fnmatch.h>
10
11 #include "alloc-util.h"
12 //#include "blockdev-util.h"
13 //#include "bpf-firewall.h"
14 //#include "bus-error.h"
15 #include "cgroup-util.h"
16 #include "cgroup.h"
17 #include "fd-util.h"
18 #include "fileio.h"
19 #include "fs-util.h"
20 #include "parse-util.h"
21 #include "path-util.h"
22 #include "process-util.h"
23 //#include "procfs-util.h"
24 //#include "special.h"
25 #include "stdio-util.h"
26 #include "string-table.h"
27 #include "string-util.h"
28 #include "virt.h"
29
30 #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
31
32 bool manager_owns_root_cgroup(Manager *m) {
33         assert(m);
34
35         /* Returns true if we are managing the root cgroup. Note that it isn't sufficient to just check whether the
36          * group root path equals "/" since that will also be the case if CLONE_NEWCGROUP is in the mix. Since there's
37          * appears to be no nice way to detect whether we are in a CLONE_NEWCGROUP namespace we instead just check if
38          * we run in any kind of container virtualization. */
39
40         if (detect_container() > 0)
41                 return false;
42
43         return empty_or_root(m->cgroup_root);
44 }
45
46 #if 0 /// UNNEEDED by elogind
47 bool unit_has_root_cgroup(Unit *u) {
48         assert(u);
49
50         /* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and
51          * the manager manages the root cgroup. */
52
53         if (!manager_owns_root_cgroup(u->manager))
54                 return false;
55
56         return unit_has_name(u, SPECIAL_ROOT_SLICE);
57 }
58
59 static void cgroup_compat_warn(void) {
60         static bool cgroup_compat_warned = false;
61
62         if (cgroup_compat_warned)
63                 return;
64
65         log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. "
66                     "See cgroup-compat debug messages for details.");
67
68         cgroup_compat_warned = true;
69 }
70
71 #define log_cgroup_compat(unit, fmt, ...) do {                                  \
72                 cgroup_compat_warn();                                           \
73                 log_unit_debug(unit, "cgroup-compat: " fmt, ##__VA_ARGS__);     \
74         } while (false)
75
76 void cgroup_context_init(CGroupContext *c) {
77         assert(c);
78
79         /* Initialize everything to the kernel defaults, assuming the
80          * structure is preinitialized to 0 */
81
82         c->cpu_weight = CGROUP_WEIGHT_INVALID;
83         c->startup_cpu_weight = CGROUP_WEIGHT_INVALID;
84         c->cpu_quota_per_sec_usec = USEC_INFINITY;
85
86         c->cpu_shares = CGROUP_CPU_SHARES_INVALID;
87         c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
88
89         c->memory_high = CGROUP_LIMIT_MAX;
90         c->memory_max = CGROUP_LIMIT_MAX;
91         c->memory_swap_max = CGROUP_LIMIT_MAX;
92
93         c->memory_limit = CGROUP_LIMIT_MAX;
94
95         c->io_weight = CGROUP_WEIGHT_INVALID;
96         c->startup_io_weight = CGROUP_WEIGHT_INVALID;
97
98         c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
99         c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
100
101         c->tasks_max = (uint64_t) -1;
102 }
103
104 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
105         assert(c);
106         assert(a);
107
108         LIST_REMOVE(device_allow, c->device_allow, a);
109         free(a->path);
110         free(a);
111 }
112
113 void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w) {
114         assert(c);
115         assert(w);
116
117         LIST_REMOVE(device_weights, c->io_device_weights, w);
118         free(w->path);
119         free(w);
120 }
121
122 void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l) {
123         assert(c);
124         assert(l);
125
126         LIST_REMOVE(device_limits, c->io_device_limits, l);
127         free(l->path);
128         free(l);
129 }
130
131 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
132         assert(c);
133         assert(w);
134
135         LIST_REMOVE(device_weights, c->blockio_device_weights, w);
136         free(w->path);
137         free(w);
138 }
139
140 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
141         assert(c);
142         assert(b);
143
144         LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b);
145         free(b->path);
146         free(b);
147 }
148
149 void cgroup_context_done(CGroupContext *c) {
150         assert(c);
151
152         while (c->io_device_weights)
153                 cgroup_context_free_io_device_weight(c, c->io_device_weights);
154
155         while (c->io_device_limits)
156                 cgroup_context_free_io_device_limit(c, c->io_device_limits);
157
158         while (c->blockio_device_weights)
159                 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
160
161         while (c->blockio_device_bandwidths)
162                 cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
163
164         while (c->device_allow)
165                 cgroup_context_free_device_allow(c, c->device_allow);
166
167         c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
168         c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
169 }
170
171 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
172         CGroupIODeviceLimit *il;
173         CGroupIODeviceWeight *iw;
174         CGroupBlockIODeviceBandwidth *b;
175         CGroupBlockIODeviceWeight *w;
176         CGroupDeviceAllow *a;
177         IPAddressAccessItem *iaai;
178         char u[FORMAT_TIMESPAN_MAX];
179
180         assert(c);
181         assert(f);
182
183         prefix = strempty(prefix);
184
185         fprintf(f,
186                 "%sCPUAccounting=%s\n"
187                 "%sIOAccounting=%s\n"
188                 "%sBlockIOAccounting=%s\n"
189                 "%sMemoryAccounting=%s\n"
190                 "%sTasksAccounting=%s\n"
191                 "%sIPAccounting=%s\n"
192                 "%sCPUWeight=%" PRIu64 "\n"
193                 "%sStartupCPUWeight=%" PRIu64 "\n"
194                 "%sCPUShares=%" PRIu64 "\n"
195                 "%sStartupCPUShares=%" PRIu64 "\n"
196                 "%sCPUQuotaPerSecSec=%s\n"
197                 "%sIOWeight=%" PRIu64 "\n"
198                 "%sStartupIOWeight=%" PRIu64 "\n"
199                 "%sBlockIOWeight=%" PRIu64 "\n"
200                 "%sStartupBlockIOWeight=%" PRIu64 "\n"
201                 "%sMemoryLow=%" PRIu64 "\n"
202                 "%sMemoryHigh=%" PRIu64 "\n"
203                 "%sMemoryMax=%" PRIu64 "\n"
204                 "%sMemorySwapMax=%" PRIu64 "\n"
205                 "%sMemoryLimit=%" PRIu64 "\n"
206                 "%sTasksMax=%" PRIu64 "\n"
207                 "%sDevicePolicy=%s\n"
208                 "%sDelegate=%s\n",
209                 prefix, yes_no(c->cpu_accounting),
210                 prefix, yes_no(c->io_accounting),
211                 prefix, yes_no(c->blockio_accounting),
212                 prefix, yes_no(c->memory_accounting),
213                 prefix, yes_no(c->tasks_accounting),
214                 prefix, yes_no(c->ip_accounting),
215                 prefix, c->cpu_weight,
216                 prefix, c->startup_cpu_weight,
217                 prefix, c->cpu_shares,
218                 prefix, c->startup_cpu_shares,
219                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
220                 prefix, c->io_weight,
221                 prefix, c->startup_io_weight,
222                 prefix, c->blockio_weight,
223                 prefix, c->startup_blockio_weight,
224                 prefix, c->memory_low,
225                 prefix, c->memory_high,
226                 prefix, c->memory_max,
227                 prefix, c->memory_swap_max,
228                 prefix, c->memory_limit,
229                 prefix, c->tasks_max,
230                 prefix, cgroup_device_policy_to_string(c->device_policy),
231                 prefix, yes_no(c->delegate));
232
233         if (c->delegate) {
234                 _cleanup_free_ char *t = NULL;
235
236                 (void) cg_mask_to_string(c->delegate_controllers, &t);
237
238                 fprintf(f, "%sDelegateControllers=%s\n",
239                         prefix,
240                         strempty(t));
241         }
242
243         LIST_FOREACH(device_allow, a, c->device_allow)
244                 fprintf(f,
245                         "%sDeviceAllow=%s %s%s%s\n",
246                         prefix,
247                         a->path,
248                         a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
249
250         LIST_FOREACH(device_weights, iw, c->io_device_weights)
251                 fprintf(f,
252                         "%sIODeviceWeight=%s %" PRIu64,
253                         prefix,
254                         iw->path,
255                         iw->weight);
256
257         LIST_FOREACH(device_limits, il, c->io_device_limits) {
258                 char buf[FORMAT_BYTES_MAX];
259                 CGroupIOLimitType type;
260
261                 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
262                         if (il->limits[type] != cgroup_io_limit_defaults[type])
263                                 fprintf(f,
264                                         "%s%s=%s %s\n",
265                                         prefix,
266                                         cgroup_io_limit_type_to_string(type),
267                                         il->path,
268                                         format_bytes(buf, sizeof(buf), il->limits[type]));
269         }
270
271         LIST_FOREACH(device_weights, w, c->blockio_device_weights)
272                 fprintf(f,
273                         "%sBlockIODeviceWeight=%s %" PRIu64,
274                         prefix,
275                         w->path,
276                         w->weight);
277
278         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
279                 char buf[FORMAT_BYTES_MAX];
280
281                 if (b->rbps != CGROUP_LIMIT_MAX)
282                         fprintf(f,
283                                 "%sBlockIOReadBandwidth=%s %s\n",
284                                 prefix,
285                                 b->path,
286                                 format_bytes(buf, sizeof(buf), b->rbps));
287                 if (b->wbps != CGROUP_LIMIT_MAX)
288                         fprintf(f,
289                                 "%sBlockIOWriteBandwidth=%s %s\n",
290                                 prefix,
291                                 b->path,
292                                 format_bytes(buf, sizeof(buf), b->wbps));
293         }
294
295         LIST_FOREACH(items, iaai, c->ip_address_allow) {
296                 _cleanup_free_ char *k = NULL;
297
298                 (void) in_addr_to_string(iaai->family, &iaai->address, &k);
299                 fprintf(f, "%sIPAddressAllow=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
300         }
301
302         LIST_FOREACH(items, iaai, c->ip_address_deny) {
303                 _cleanup_free_ char *k = NULL;
304
305                 (void) in_addr_to_string(iaai->family, &iaai->address, &k);
306                 fprintf(f, "%sIPAddressDeny=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
307         }
308 }
309
310 static int lookup_block_device(const char *p, dev_t *dev) {
311         struct stat st;
312         int r;
313
314         assert(p);
315         assert(dev);
316
317         r = stat(p, &st);
318         if (r < 0)
319                 return log_warning_errno(errno, "Couldn't stat device %s: %m", p);
320
321         if (S_ISBLK(st.st_mode))
322                 *dev = st.st_rdev;
323         else if (major(st.st_dev) != 0) {
324                 /* If this is not a device node then find the block
325                  * device this file is stored on */
326                 *dev = st.st_dev;
327
328                 /* If this is a partition, try to get the originating
329                  * block device */
330                 (void) block_get_whole_disk(*dev, dev);
331         } else {
332                 log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
333                 return -ENODEV;
334         }
335
336         return 0;
337 }
338
339 static int whitelist_device(const char *path, const char *node, const char *acc) {
340         char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
341         struct stat st;
342         bool ignore_notfound;
343         int r;
344
345         assert(path);
346         assert(acc);
347
348         if (node[0] == '-') {
349                 /* Non-existent paths starting with "-" must be silently ignored */
350                 node++;
351                 ignore_notfound = true;
352         } else
353                 ignore_notfound = false;
354
355         if (stat(node, &st) < 0) {
356                 if (errno == ENOENT && ignore_notfound)
357                         return 0;
358
359                 return log_warning_errno(errno, "Couldn't stat device %s: %m", node);
360         }
361
362         if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
363                 log_warning("%s is not a device.", node);
364                 return -ENODEV;
365         }
366
367         sprintf(buf,
368                 "%c %u:%u %s",
369                 S_ISCHR(st.st_mode) ? 'c' : 'b',
370                 major(st.st_rdev), minor(st.st_rdev),
371                 acc);
372
373         r = cg_set_attribute("devices", path, "devices.allow", buf);
374         if (r < 0)
375                 log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
376                                "Failed to set devices.allow on %s: %m", path);
377
378         return r;
379 }
380
381 static int whitelist_major(const char *path, const char *name, char type, const char *acc) {
382         _cleanup_fclose_ FILE *f = NULL;
383         char line[LINE_MAX];
384         bool good = false;
385         int r;
386
387         assert(path);
388         assert(acc);
389         assert(IN_SET(type, 'b', 'c'));
390
391         f = fopen("/proc/devices", "re");
392         if (!f)
393                 return log_warning_errno(errno, "Cannot open /proc/devices to resolve %s (%c): %m", name, type);
394
395         FOREACH_LINE(line, f, goto fail) {
396                 char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w;
397                 unsigned maj;
398
399                 truncate_nl(line);
400
401                 if (type == 'c' && streq(line, "Character devices:")) {
402                         good = true;
403                         continue;
404                 }
405
406                 if (type == 'b' && streq(line, "Block devices:")) {
407                         good = true;
408                         continue;
409                 }
410
411                 if (isempty(line)) {
412                         good = false;
413                         continue;
414                 }
415
416                 if (!good)
417                         continue;
418
419                 p = strstrip(line);
420
421                 w = strpbrk(p, WHITESPACE);
422                 if (!w)
423                         continue;
424                 *w = 0;
425
426                 r = safe_atou(p, &maj);
427                 if (r < 0)
428                         continue;
429                 if (maj <= 0)
430                         continue;
431
432                 w++;
433                 w += strspn(w, WHITESPACE);
434
435                 if (fnmatch(name, w, 0) != 0)
436                         continue;
437
438                 sprintf(buf,
439                         "%c %u:* %s",
440                         type,
441                         maj,
442                         acc);
443
444                 r = cg_set_attribute("devices", path, "devices.allow", buf);
445                 if (r < 0)
446                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
447                                        "Failed to set devices.allow on %s: %m", path);
448         }
449
450         return 0;
451
452 fail:
453         return log_warning_errno(errno, "Failed to read /proc/devices: %m");
454 }
455
456 static bool cgroup_context_has_cpu_weight(CGroupContext *c) {
457         return c->cpu_weight != CGROUP_WEIGHT_INVALID ||
458                 c->startup_cpu_weight != CGROUP_WEIGHT_INVALID;
459 }
460
461 static bool cgroup_context_has_cpu_shares(CGroupContext *c) {
462         return c->cpu_shares != CGROUP_CPU_SHARES_INVALID ||
463                 c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID;
464 }
465
466 static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) {
467         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
468             c->startup_cpu_weight != CGROUP_WEIGHT_INVALID)
469                 return c->startup_cpu_weight;
470         else if (c->cpu_weight != CGROUP_WEIGHT_INVALID)
471                 return c->cpu_weight;
472         else
473                 return CGROUP_WEIGHT_DEFAULT;
474 }
475
476 static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state) {
477         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
478             c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID)
479                 return c->startup_cpu_shares;
480         else if (c->cpu_shares != CGROUP_CPU_SHARES_INVALID)
481                 return c->cpu_shares;
482         else
483                 return CGROUP_CPU_SHARES_DEFAULT;
484 }
485
486 static void cgroup_apply_unified_cpu_config(Unit *u, uint64_t weight, uint64_t quota) {
487         char buf[MAX(DECIMAL_STR_MAX(uint64_t) + 1, (DECIMAL_STR_MAX(usec_t) + 1) * 2)];
488         int r;
489
490         xsprintf(buf, "%" PRIu64 "\n", weight);
491         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.weight", buf);
492         if (r < 0)
493                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
494                               "Failed to set cpu.weight: %m");
495
496         if (quota != USEC_INFINITY)
497                 xsprintf(buf, USEC_FMT " " USEC_FMT "\n",
498                          quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC, CGROUP_CPU_QUOTA_PERIOD_USEC);
499         else
500                 xsprintf(buf, "max " USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
501
502         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.max", buf);
503
504         if (r < 0)
505                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
506                               "Failed to set cpu.max: %m");
507 }
508
509 static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota) {
510         char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
511         int r;
512
513         xsprintf(buf, "%" PRIu64 "\n", shares);
514         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.shares", buf);
515         if (r < 0)
516                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
517                               "Failed to set cpu.shares: %m");
518
519         xsprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
520         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_period_us", buf);
521         if (r < 0)
522                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
523                               "Failed to set cpu.cfs_period_us: %m");
524
525         if (quota != USEC_INFINITY) {
526                 xsprintf(buf, USEC_FMT "\n", quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
527                 r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", buf);
528         } else
529                 r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", "-1");
530         if (r < 0)
531                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
532                               "Failed to set cpu.cfs_quota_us: %m");
533 }
534
535 static uint64_t cgroup_cpu_shares_to_weight(uint64_t shares) {
536         return CLAMP(shares * CGROUP_WEIGHT_DEFAULT / CGROUP_CPU_SHARES_DEFAULT,
537                      CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX);
538 }
539
540 static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) {
541         return CLAMP(weight * CGROUP_CPU_SHARES_DEFAULT / CGROUP_WEIGHT_DEFAULT,
542                      CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX);
543 }
544
545 static bool cgroup_context_has_io_config(CGroupContext *c) {
546         return c->io_accounting ||
547                 c->io_weight != CGROUP_WEIGHT_INVALID ||
548                 c->startup_io_weight != CGROUP_WEIGHT_INVALID ||
549                 c->io_device_weights ||
550                 c->io_device_limits;
551 }
552
553 static bool cgroup_context_has_blockio_config(CGroupContext *c) {
554         return c->blockio_accounting ||
555                 c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
556                 c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
557                 c->blockio_device_weights ||
558                 c->blockio_device_bandwidths;
559 }
560
561 static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) {
562         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
563             c->startup_io_weight != CGROUP_WEIGHT_INVALID)
564                 return c->startup_io_weight;
565         else if (c->io_weight != CGROUP_WEIGHT_INVALID)
566                 return c->io_weight;
567         else
568                 return CGROUP_WEIGHT_DEFAULT;
569 }
570
571 static uint64_t cgroup_context_blkio_weight(CGroupContext *c, ManagerState state) {
572         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
573             c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
574                 return c->startup_blockio_weight;
575         else if (c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
576                 return c->blockio_weight;
577         else
578                 return CGROUP_BLKIO_WEIGHT_DEFAULT;
579 }
580
581 static uint64_t cgroup_weight_blkio_to_io(uint64_t blkio_weight) {
582         return CLAMP(blkio_weight * CGROUP_WEIGHT_DEFAULT / CGROUP_BLKIO_WEIGHT_DEFAULT,
583                      CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX);
584 }
585
586 static uint64_t cgroup_weight_io_to_blkio(uint64_t io_weight) {
587         return CLAMP(io_weight * CGROUP_BLKIO_WEIGHT_DEFAULT / CGROUP_WEIGHT_DEFAULT,
588                      CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX);
589 }
590
591 static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_t io_weight) {
592         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
593         dev_t dev;
594         int r;
595
596         r = lookup_block_device(dev_path, &dev);
597         if (r < 0)
598                 return;
599
600         xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), io_weight);
601         r = cg_set_attribute("io", u->cgroup_path, "io.weight", buf);
602         if (r < 0)
603                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
604                               "Failed to set io.weight: %m");
605 }
606
607 static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint64_t blkio_weight) {
608         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
609         dev_t dev;
610         int r;
611
612         r = lookup_block_device(dev_path, &dev);
613         if (r < 0)
614                 return;
615
616         xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), blkio_weight);
617         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.weight_device", buf);
618         if (r < 0)
619                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
620                               "Failed to set blkio.weight_device: %m");
621 }
622
623 static unsigned cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
624         char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
625         char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
626         CGroupIOLimitType type;
627         dev_t dev;
628         unsigned n = 0;
629         int r;
630
631         r = lookup_block_device(dev_path, &dev);
632         if (r < 0)
633                 return 0;
634
635         for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) {
636                 if (limits[type] != cgroup_io_limit_defaults[type]) {
637                         xsprintf(limit_bufs[type], "%" PRIu64, limits[type]);
638                         n++;
639                 } else {
640                         xsprintf(limit_bufs[type], "%s", limits[type] == CGROUP_LIMIT_MAX ? "max" : "0");
641                 }
642         }
643
644         xsprintf(buf, "%u:%u rbps=%s wbps=%s riops=%s wiops=%s\n", major(dev), minor(dev),
645                  limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX],
646                  limit_bufs[CGROUP_IO_RIOPS_MAX], limit_bufs[CGROUP_IO_WIOPS_MAX]);
647         r = cg_set_attribute("io", u->cgroup_path, "io.max", buf);
648         if (r < 0)
649                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
650                               "Failed to set io.max: %m");
651         return n;
652 }
653
654 static unsigned cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
655         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
656         dev_t dev;
657         unsigned n = 0;
658         int r;
659
660         r = lookup_block_device(dev_path, &dev);
661         if (r < 0)
662                 return 0;
663
664         if (rbps != CGROUP_LIMIT_MAX)
665                 n++;
666         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps);
667         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.read_bps_device", buf);
668         if (r < 0)
669                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
670                               "Failed to set blkio.throttle.read_bps_device: %m");
671
672         if (wbps != CGROUP_LIMIT_MAX)
673                 n++;
674         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), wbps);
675         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.write_bps_device", buf);
676         if (r < 0)
677                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
678                               "Failed to set blkio.throttle.write_bps_device: %m");
679
680         return n;
681 }
682
683 static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
684         return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX;
685 }
686
687 static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) {
688         char buf[DECIMAL_STR_MAX(uint64_t) + 1] = "max";
689         int r;
690
691         if (v != CGROUP_LIMIT_MAX)
692                 xsprintf(buf, "%" PRIu64 "\n", v);
693
694         r = cg_set_attribute("memory", u->cgroup_path, file, buf);
695         if (r < 0)
696                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
697                               "Failed to set %s: %m", file);
698 }
699
700 static void cgroup_apply_firewall(Unit *u) {
701         assert(u);
702
703         /* Best-effort: let's apply IP firewalling and/or accounting if that's enabled */
704
705         if (bpf_firewall_compile(u) < 0)
706                 return;
707
708         (void) bpf_firewall_install(u);
709 }
710
711 static void cgroup_context_apply(
712                 Unit *u,
713                 CGroupMask apply_mask,
714                 bool apply_bpf,
715                 ManagerState state) {
716
717         const char *path;
718         CGroupContext *c;
719         bool is_root;
720         int r;
721
722         assert(u);
723
724         /* Nothing to do? Exit early! */
725         if (apply_mask == 0 && !apply_bpf)
726                 return;
727
728         /* Some cgroup attributes are not supported on the root cgroup, hence silently ignore */
729         is_root = unit_has_root_cgroup(u);
730
731         assert_se(c = unit_get_cgroup_context(u));
732         assert_se(path = u->cgroup_path);
733
734         if (is_root) /* Make sure we don't try to display messages with an empty path. */
735                 path = "/";
736
737         /* We generally ignore errors caused by read-only mounted
738          * cgroup trees (assuming we are running in a container then),
739          * and missing cgroups, i.e. EROFS and ENOENT. */
740
741         if ((apply_mask & CGROUP_MASK_CPU) && !is_root) {
742                 bool has_weight, has_shares;
743
744                 has_weight = cgroup_context_has_cpu_weight(c);
745                 has_shares = cgroup_context_has_cpu_shares(c);
746
747                 if (cg_all_unified() > 0) {
748                         uint64_t weight;
749
750                         if (has_weight)
751                                 weight = cgroup_context_cpu_weight(c, state);
752                         else if (has_shares) {
753                                 uint64_t shares = cgroup_context_cpu_shares(c, state);
754
755                                 weight = cgroup_cpu_shares_to_weight(shares);
756
757                                 log_cgroup_compat(u, "Applying [Startup]CpuShares %" PRIu64 " as [Startup]CpuWeight %" PRIu64 " on %s",
758                                                   shares, weight, path);
759                         } else
760                                 weight = CGROUP_WEIGHT_DEFAULT;
761
762                         cgroup_apply_unified_cpu_config(u, weight, c->cpu_quota_per_sec_usec);
763                 } else {
764                         uint64_t shares;
765
766                         if (has_weight) {
767                                 uint64_t weight = cgroup_context_cpu_weight(c, state);
768
769                                 shares = cgroup_cpu_weight_to_shares(weight);
770
771                                 log_cgroup_compat(u, "Applying [Startup]CpuWeight %" PRIu64 " as [Startup]CpuShares %" PRIu64 " on %s",
772                                                   weight, shares, path);
773                         } else if (has_shares)
774                                 shares = cgroup_context_cpu_shares(c, state);
775                         else
776                                 shares = CGROUP_CPU_SHARES_DEFAULT;
777
778                         cgroup_apply_legacy_cpu_config(u, shares, c->cpu_quota_per_sec_usec);
779                 }
780         }
781
782         if (apply_mask & CGROUP_MASK_IO) {
783                 bool has_io = cgroup_context_has_io_config(c);
784                 bool has_blockio = cgroup_context_has_blockio_config(c);
785
786                 if (!is_root) {
787                         char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
788                         uint64_t weight;
789
790                         if (has_io)
791                                 weight = cgroup_context_io_weight(c, state);
792                         else if (has_blockio) {
793                                 uint64_t blkio_weight = cgroup_context_blkio_weight(c, state);
794
795                                 weight = cgroup_weight_blkio_to_io(blkio_weight);
796
797                                 log_cgroup_compat(u, "Applying [Startup]BlockIOWeight %" PRIu64 " as [Startup]IOWeight %" PRIu64,
798                                                   blkio_weight, weight);
799                         } else
800                                 weight = CGROUP_WEIGHT_DEFAULT;
801
802                         xsprintf(buf, "default %" PRIu64 "\n", weight);
803                         r = cg_set_attribute("io", path, "io.weight", buf);
804                         if (r < 0)
805                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
806                                               "Failed to set io.weight: %m");
807
808                         if (has_io) {
809                                 CGroupIODeviceWeight *w;
810
811                                 /* FIXME: no way to reset this list */
812                                 LIST_FOREACH(device_weights, w, c->io_device_weights)
813                                         cgroup_apply_io_device_weight(u, w->path, w->weight);
814                         } else if (has_blockio) {
815                                 CGroupBlockIODeviceWeight *w;
816
817                                 /* FIXME: no way to reset this list */
818                                 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
819                                         weight = cgroup_weight_blkio_to_io(w->weight);
820
821                                         log_cgroup_compat(u, "Applying BlockIODeviceWeight %" PRIu64 " as IODeviceWeight %" PRIu64 " for %s",
822                                                           w->weight, weight, w->path);
823
824                                         cgroup_apply_io_device_weight(u, w->path, weight);
825                                 }
826                         }
827                 }
828
829                 /* Apply limits and free ones without config. */
830                 if (has_io) {
831                         CGroupIODeviceLimit *l, *next;
832
833                         LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
834                                 if (!cgroup_apply_io_device_limit(u, l->path, l->limits))
835                                         cgroup_context_free_io_device_limit(c, l);
836                         }
837                 } else if (has_blockio) {
838                         CGroupBlockIODeviceBandwidth *b, *next;
839
840                         LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) {
841                                 uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
842                                 CGroupIOLimitType type;
843
844                                 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
845                                         limits[type] = cgroup_io_limit_defaults[type];
846
847                                 limits[CGROUP_IO_RBPS_MAX] = b->rbps;
848                                 limits[CGROUP_IO_WBPS_MAX] = b->wbps;
849
850                                 log_cgroup_compat(u, "Applying BlockIO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as IO{Read|Write}BandwidthMax for %s",
851                                                   b->rbps, b->wbps, b->path);
852
853                                 if (!cgroup_apply_io_device_limit(u, b->path, limits))
854                                         cgroup_context_free_blockio_device_bandwidth(c, b);
855                         }
856                 }
857         }
858
859         if (apply_mask & CGROUP_MASK_BLKIO) {
860                 bool has_io = cgroup_context_has_io_config(c);
861                 bool has_blockio = cgroup_context_has_blockio_config(c);
862
863                 if (!is_root) {
864                         char buf[DECIMAL_STR_MAX(uint64_t)+1];
865                         uint64_t weight;
866
867                         if (has_io) {
868                                 uint64_t io_weight = cgroup_context_io_weight(c, state);
869
870                                 weight = cgroup_weight_io_to_blkio(cgroup_context_io_weight(c, state));
871
872                                 log_cgroup_compat(u, "Applying [Startup]IOWeight %" PRIu64 " as [Startup]BlockIOWeight %" PRIu64,
873                                                   io_weight, weight);
874                         } else if (has_blockio)
875                                 weight = cgroup_context_blkio_weight(c, state);
876                         else
877                                 weight = CGROUP_BLKIO_WEIGHT_DEFAULT;
878
879                         xsprintf(buf, "%" PRIu64 "\n", weight);
880                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
881                         if (r < 0)
882                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
883                                               "Failed to set blkio.weight: %m");
884
885                         if (has_io) {
886                                 CGroupIODeviceWeight *w;
887
888                                 /* FIXME: no way to reset this list */
889                                 LIST_FOREACH(device_weights, w, c->io_device_weights) {
890                                         weight = cgroup_weight_io_to_blkio(w->weight);
891
892                                         log_cgroup_compat(u, "Applying IODeviceWeight %" PRIu64 " as BlockIODeviceWeight %" PRIu64 " for %s",
893                                                           w->weight, weight, w->path);
894
895                                         cgroup_apply_blkio_device_weight(u, w->path, weight);
896                                 }
897                         } else if (has_blockio) {
898                                 CGroupBlockIODeviceWeight *w;
899
900                                 /* FIXME: no way to reset this list */
901                                 LIST_FOREACH(device_weights, w, c->blockio_device_weights)
902                                         cgroup_apply_blkio_device_weight(u, w->path, w->weight);
903                         }
904                 }
905
906                 /* Apply limits and free ones without config. */
907                 if (has_io) {
908                         CGroupIODeviceLimit *l, *next;
909
910                         LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
911                                 log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax for %s",
912                                                   l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path);
913
914                                 if (!cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]))
915                                         cgroup_context_free_io_device_limit(c, l);
916                         }
917                 } else if (has_blockio) {
918                         CGroupBlockIODeviceBandwidth *b, *next;
919
920                         LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths)
921                                 if (!cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps))
922                                         cgroup_context_free_blockio_device_bandwidth(c, b);
923                 }
924         }
925
926         if ((apply_mask & CGROUP_MASK_MEMORY) && !is_root) {
927                 if (cg_all_unified() > 0) {
928                         uint64_t max, swap_max = CGROUP_LIMIT_MAX;
929
930                         if (cgroup_context_has_unified_memory_config(c)) {
931                                 max = c->memory_max;
932                                 swap_max = c->memory_swap_max;
933                         } else {
934                                 max = c->memory_limit;
935
936                                 if (max != CGROUP_LIMIT_MAX)
937                                         log_cgroup_compat(u, "Applying MemoryLimit %" PRIu64 " as MemoryMax", max);
938                         }
939
940                         cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low);
941                         cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high);
942                         cgroup_apply_unified_memory_limit(u, "memory.max", max);
943                         cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max);
944                 } else {
945                         char buf[DECIMAL_STR_MAX(uint64_t) + 1];
946                         uint64_t val;
947
948                         if (cgroup_context_has_unified_memory_config(c)) {
949                                 val = c->memory_max;
950                                 log_cgroup_compat(u, "Applying MemoryMax %" PRIi64 " as MemoryLimit", val);
951                         } else
952                                 val = c->memory_limit;
953
954                         if (val == CGROUP_LIMIT_MAX)
955                                 strncpy(buf, "-1\n", sizeof(buf));
956                         else
957                                 xsprintf(buf, "%" PRIu64 "\n", val);
958
959                         r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
960                         if (r < 0)
961                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
962                                               "Failed to set memory.limit_in_bytes: %m");
963                 }
964         }
965
966         if ((apply_mask & CGROUP_MASK_DEVICES) && !is_root) {
967                 CGroupDeviceAllow *a;
968
969                 /* Changing the devices list of a populated cgroup
970                  * might result in EINVAL, hence ignore EINVAL
971                  * here. */
972
973                 if (c->device_allow || c->device_policy != CGROUP_AUTO)
974                         r = cg_set_attribute("devices", path, "devices.deny", "a");
975                 else
976                         r = cg_set_attribute("devices", path, "devices.allow", "a");
977                 if (r < 0)
978                         log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
979                                       "Failed to reset devices.list: %m");
980
981                 if (c->device_policy == CGROUP_CLOSED ||
982                     (c->device_policy == CGROUP_AUTO && c->device_allow)) {
983                         static const char auto_devices[] =
984                                 "/dev/null\0" "rwm\0"
985                                 "/dev/zero\0" "rwm\0"
986                                 "/dev/full\0" "rwm\0"
987                                 "/dev/random\0" "rwm\0"
988                                 "/dev/urandom\0" "rwm\0"
989                                 "/dev/tty\0" "rwm\0"
990                                 "/dev/ptmx\0" "rwm\0"
991                                 /* Allow /run/systemd/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */
992                                 "-/run/systemd/inaccessible/chr\0" "rwm\0"
993                                 "-/run/systemd/inaccessible/blk\0" "rwm\0";
994
995                         const char *x, *y;
996
997                         NULSTR_FOREACH_PAIR(x, y, auto_devices)
998                                 whitelist_device(path, x, y);
999
1000                         /* PTS (/dev/pts) devices may not be duplicated, but accessed */
1001                         whitelist_major(path, "pts", 'c', "rw");
1002                 }
1003
1004                 LIST_FOREACH(device_allow, a, c->device_allow) {
1005                         char acc[4], *val;
1006                         unsigned k = 0;
1007
1008                         if (a->r)
1009                                 acc[k++] = 'r';
1010                         if (a->w)
1011                                 acc[k++] = 'w';
1012                         if (a->m)
1013                                 acc[k++] = 'm';
1014
1015                         if (k == 0)
1016                                 continue;
1017
1018                         acc[k++] = 0;
1019
1020                         if (path_startswith(a->path, "/dev/"))
1021                                 whitelist_device(path, a->path, acc);
1022                         else if ((val = startswith(a->path, "block-")))
1023                                 whitelist_major(path, val, 'b', acc);
1024                         else if ((val = startswith(a->path, "char-")))
1025                                 whitelist_major(path, val, 'c', acc);
1026                         else
1027                                 log_unit_debug(u, "Ignoring device %s while writing cgroup attribute.", a->path);
1028                 }
1029         }
1030
1031         if (apply_mask & CGROUP_MASK_PIDS) {
1032
1033                 if (is_root) {
1034                         /* So, the "pids" controller does not expose anything on the root cgroup, in order not to
1035                          * replicate knobs exposed elsewhere needlessly. We abstract this away here however, and when
1036                          * the knobs of the root cgroup are modified propagate this to the relevant sysctls. There's a
1037                          * non-obvious asymmetry however: unlike the cgroup properties we don't really want to take
1038                          * exclusive ownership of the sysctls, but we still want to honour things if the user sets
1039                          * limits. Hence we employ sort of a one-way strategy: when the user sets a bounded limit
1040                          * through us it counts. When the user afterwards unsets it again (i.e. sets it to unbounded)
1041                          * it also counts. But if the user never set a limit through us (i.e. we are the default of
1042                          * "unbounded") we leave things unmodified. For this we manage a global boolean that we turn on
1043                          * the first time we set a limit. Note that this boolean is flushed out on manager reload,
1044                          * which is desirable so that there's an offical way to release control of the sysctl from
1045                          * systemd: set the limit to unbounded and reload. */
1046
1047                         if (c->tasks_max != CGROUP_LIMIT_MAX) {
1048                                 u->manager->sysctl_pid_max_changed = true;
1049                                 r = procfs_tasks_set_limit(c->tasks_max);
1050                         } else if (u->manager->sysctl_pid_max_changed)
1051                                 r = procfs_tasks_set_limit(TASKS_MAX);
1052                         else
1053                                 r = 0;
1054
1055                         if (r < 0)
1056                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
1057                                               "Failed to write to tasks limit sysctls: %m");
1058
1059                 } else {
1060                         if (c->tasks_max != CGROUP_LIMIT_MAX) {
1061                                 char buf[DECIMAL_STR_MAX(uint64_t) + 2];
1062
1063                                 sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
1064                                 r = cg_set_attribute("pids", path, "pids.max", buf);
1065                         } else
1066                                 r = cg_set_attribute("pids", path, "pids.max", "max");
1067                         if (r < 0)
1068                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
1069                                               "Failed to set pids.max: %m");
1070                 }
1071         }
1072
1073         if (apply_bpf)
1074                 cgroup_apply_firewall(u);
1075 }
1076
1077 CGroupMask cgroup_context_get_mask(CGroupContext *c) {
1078         CGroupMask mask = 0;
1079
1080         /* Figure out which controllers we need */
1081
1082         if (c->cpu_accounting ||
1083             cgroup_context_has_cpu_weight(c) ||
1084             cgroup_context_has_cpu_shares(c) ||
1085             c->cpu_quota_per_sec_usec != USEC_INFINITY)
1086                 mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
1087
1088         if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c))
1089                 mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
1090
1091         if (c->memory_accounting ||
1092             c->memory_limit != CGROUP_LIMIT_MAX ||
1093             cgroup_context_has_unified_memory_config(c))
1094                 mask |= CGROUP_MASK_MEMORY;
1095
1096         if (c->device_allow ||
1097             c->device_policy != CGROUP_AUTO)
1098                 mask |= CGROUP_MASK_DEVICES;
1099
1100         if (c->tasks_accounting ||
1101             c->tasks_max != CGROUP_LIMIT_MAX)
1102                 mask |= CGROUP_MASK_PIDS;
1103
1104         return mask;
1105 }
1106
1107 CGroupMask unit_get_own_mask(Unit *u) {
1108         CGroupContext *c;
1109
1110         /* Returns the mask of controllers the unit needs for itself */
1111
1112         c = unit_get_cgroup_context(u);
1113         if (!c)
1114                 return 0;
1115
1116         return cgroup_context_get_mask(c) | unit_get_delegate_mask(u);
1117 }
1118
1119 CGroupMask unit_get_delegate_mask(Unit *u) {
1120         CGroupContext *c;
1121
1122         /* If delegation is turned on, then turn on selected controllers, unless we are on the legacy hierarchy and the
1123          * process we fork into is known to drop privileges, and hence shouldn't get access to the controllers.
1124          *
1125          * Note that on the unified hierarchy it is safe to delegate controllers to unprivileged services. */
1126
1127         if (!unit_cgroup_delegate(u))
1128                 return 0;
1129
1130         if (cg_all_unified() <= 0) {
1131                 ExecContext *e;
1132
1133                 e = unit_get_exec_context(u);
1134                 if (e && !exec_context_maintains_privileges(e))
1135                         return 0;
1136         }
1137
1138         assert_se(c = unit_get_cgroup_context(u));
1139         return c->delegate_controllers;
1140 }
1141
1142 CGroupMask unit_get_members_mask(Unit *u) {
1143         assert(u);
1144
1145         /* Returns the mask of controllers all of the unit's children require, merged */
1146
1147         if (u->cgroup_members_mask_valid)
1148                 return u->cgroup_members_mask;
1149
1150         u->cgroup_members_mask = 0;
1151
1152         if (u->type == UNIT_SLICE) {
1153                 void *v;
1154                 Unit *member;
1155                 Iterator i;
1156
1157                 HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
1158
1159                         if (member == u)
1160                                 continue;
1161
1162                         if (UNIT_DEREF(member->slice) != u)
1163                                 continue;
1164
1165                         u->cgroup_members_mask |= unit_get_subtree_mask(member); /* note that this calls ourselves again, for the children */
1166                 }
1167         }
1168
1169         u->cgroup_members_mask_valid = true;
1170         return u->cgroup_members_mask;
1171 }
1172
1173 CGroupMask unit_get_siblings_mask(Unit *u) {
1174         assert(u);
1175
1176         /* Returns the mask of controllers all of the unit's siblings
1177          * require, i.e. the members mask of the unit's parent slice
1178          * if there is one. */
1179
1180         if (UNIT_ISSET(u->slice))
1181                 return unit_get_members_mask(UNIT_DEREF(u->slice));
1182
1183         return unit_get_subtree_mask(u); /* we are the top-level slice */
1184 }
1185
1186 CGroupMask unit_get_subtree_mask(Unit *u) {
1187
1188         /* Returns the mask of this subtree, meaning of the group
1189          * itself and its children. */
1190
1191         return unit_get_own_mask(u) | unit_get_members_mask(u);
1192 }
1193
1194 CGroupMask unit_get_target_mask(Unit *u) {
1195         CGroupMask mask;
1196
1197         /* This returns the cgroup mask of all controllers to enable
1198          * for a specific cgroup, i.e. everything it needs itself,
1199          * plus all that its children need, plus all that its siblings
1200          * need. This is primarily useful on the legacy cgroup
1201          * hierarchy, where we need to duplicate each cgroup in each
1202          * hierarchy that shall be enabled for it. */
1203
1204         mask = unit_get_own_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
1205         mask &= u->manager->cgroup_supported;
1206
1207         return mask;
1208 }
1209
1210 CGroupMask unit_get_enable_mask(Unit *u) {
1211         CGroupMask mask;
1212
1213         /* This returns the cgroup mask of all controllers to enable
1214          * for the children of a specific cgroup. This is primarily
1215          * useful for the unified cgroup hierarchy, where each cgroup
1216          * controls which controllers are enabled for its children. */
1217
1218         mask = unit_get_members_mask(u);
1219         mask &= u->manager->cgroup_supported;
1220
1221         return mask;
1222 }
1223
1224 bool unit_get_needs_bpf(Unit *u) {
1225         CGroupContext *c;
1226         Unit *p;
1227         assert(u);
1228
1229         c = unit_get_cgroup_context(u);
1230         if (!c)
1231                 return false;
1232
1233         if (c->ip_accounting ||
1234             c->ip_address_allow ||
1235             c->ip_address_deny)
1236                 return true;
1237
1238         /* If any parent slice has an IP access list defined, it applies too */
1239         for (p = UNIT_DEREF(u->slice); p; p = UNIT_DEREF(p->slice)) {
1240                 c = unit_get_cgroup_context(p);
1241                 if (!c)
1242                         return false;
1243
1244                 if (c->ip_address_allow ||
1245                     c->ip_address_deny)
1246                         return true;
1247         }
1248
1249         return false;
1250 }
1251
1252 /* Recurse from a unit up through its containing slices, propagating
1253  * mask bits upward. A unit is also member of itself. */
1254 void unit_update_cgroup_members_masks(Unit *u) {
1255         CGroupMask m;
1256         bool more;
1257
1258         assert(u);
1259
1260         /* Calculate subtree mask */
1261         m = unit_get_subtree_mask(u);
1262
1263         /* See if anything changed from the previous invocation. If
1264          * not, we're done. */
1265         if (u->cgroup_subtree_mask_valid && m == u->cgroup_subtree_mask)
1266                 return;
1267
1268         more =
1269                 u->cgroup_subtree_mask_valid &&
1270                 ((m & ~u->cgroup_subtree_mask) != 0) &&
1271                 ((~m & u->cgroup_subtree_mask) == 0);
1272
1273         u->cgroup_subtree_mask = m;
1274         u->cgroup_subtree_mask_valid = true;
1275
1276         if (UNIT_ISSET(u->slice)) {
1277                 Unit *s = UNIT_DEREF(u->slice);
1278
1279                 if (more)
1280                         /* There's more set now than before. We
1281                          * propagate the new mask to the parent's mask
1282                          * (not caring if it actually was valid or
1283                          * not). */
1284
1285                         s->cgroup_members_mask |= m;
1286
1287                 else
1288                         /* There's less set now than before (or we
1289                          * don't know), we need to recalculate
1290                          * everything, so let's invalidate the
1291                          * parent's members mask */
1292
1293                         s->cgroup_members_mask_valid = false;
1294
1295                 /* And now make sure that this change also hits our
1296                  * grandparents */
1297                 unit_update_cgroup_members_masks(s);
1298         }
1299 }
1300
1301 const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask) {
1302
1303         /* Returns the realized cgroup path of the specified unit where all specified controllers are available. */
1304
1305         while (u) {
1306
1307                 if (u->cgroup_path &&
1308                     u->cgroup_realized &&
1309                     (u->cgroup_realized_mask & mask) == mask)
1310                         return u->cgroup_path;
1311
1312                 u = UNIT_DEREF(u->slice);
1313         }
1314
1315         return NULL;
1316 }
1317
1318 static const char *migrate_callback(CGroupMask mask, void *userdata) {
1319         return unit_get_realized_cgroup_path(userdata, mask);
1320 }
1321
1322 char *unit_default_cgroup_path(Unit *u) {
1323         _cleanup_free_ char *escaped = NULL, *slice = NULL;
1324         int r;
1325
1326         assert(u);
1327
1328         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1329                 return strdup(u->manager->cgroup_root);
1330
1331         if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) {
1332                 r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
1333                 if (r < 0)
1334                         return NULL;
1335         }
1336
1337         escaped = cg_escape(u->id);
1338         if (!escaped)
1339                 return NULL;
1340
1341         if (slice)
1342                 return strjoin(u->manager->cgroup_root, "/", slice, "/",
1343                                escaped);
1344         else
1345                 return strjoin(u->manager->cgroup_root, "/", escaped);
1346 }
1347
1348 int unit_set_cgroup_path(Unit *u, const char *path) {
1349         _cleanup_free_ char *p = NULL;
1350         int r;
1351
1352         assert(u);
1353
1354         if (path) {
1355                 p = strdup(path);
1356                 if (!p)
1357                         return -ENOMEM;
1358         } else
1359                 p = NULL;
1360
1361         if (streq_ptr(u->cgroup_path, p))
1362                 return 0;
1363
1364         if (p) {
1365                 r = hashmap_put(u->manager->cgroup_unit, p, u);
1366                 if (r < 0)
1367                         return r;
1368         }
1369
1370         unit_release_cgroup(u);
1371
1372         u->cgroup_path = TAKE_PTR(p);
1373
1374         return 1;
1375 }
1376
1377 int unit_watch_cgroup(Unit *u) {
1378         _cleanup_free_ char *events = NULL;
1379         int r;
1380
1381         assert(u);
1382
1383         if (!u->cgroup_path)
1384                 return 0;
1385
1386         if (u->cgroup_inotify_wd >= 0)
1387                 return 0;
1388
1389         /* Only applies to the unified hierarchy */
1390         r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
1391         if (r < 0)
1392                 return log_error_errno(r, "Failed to determine whether the name=systemd hierarchy is unified: %m");
1393         if (r == 0)
1394                 return 0;
1395
1396         /* Don't watch the root slice, it's pointless. */
1397         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1398                 return 0;
1399
1400         r = hashmap_ensure_allocated(&u->manager->cgroup_inotify_wd_unit, &trivial_hash_ops);
1401         if (r < 0)
1402                 return log_oom();
1403
1404         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events", &events);
1405         if (r < 0)
1406                 return log_oom();
1407
1408         u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY);
1409         if (u->cgroup_inotify_wd < 0) {
1410
1411                 if (errno == ENOENT) /* If the directory is already
1412                                       * gone we don't need to track
1413                                       * it, so this is not an error */
1414                         return 0;
1415
1416                 return log_unit_error_errno(u, errno, "Failed to add inotify watch descriptor for control group %s: %m", u->cgroup_path);
1417         }
1418
1419         r = hashmap_put(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd), u);
1420         if (r < 0)
1421                 return log_unit_error_errno(u, r, "Failed to add inotify watch descriptor to hash map: %m");
1422
1423         return 0;
1424 }
1425
1426 int unit_pick_cgroup_path(Unit *u) {
1427         _cleanup_free_ char *path = NULL;
1428         int r;
1429
1430         assert(u);
1431
1432         if (u->cgroup_path)
1433                 return 0;
1434
1435         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1436                 return -EINVAL;
1437
1438         path = unit_default_cgroup_path(u);
1439         if (!path)
1440                 return log_oom();
1441
1442         r = unit_set_cgroup_path(u, path);
1443         if (r == -EEXIST)
1444                 return log_unit_error_errno(u, r, "Control group %s exists already.", path);
1445         if (r < 0)
1446                 return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path);
1447
1448         return 0;
1449 }
1450
1451 static int unit_create_cgroup(
1452                 Unit *u,
1453                 CGroupMask target_mask,
1454                 CGroupMask enable_mask,
1455                 bool needs_bpf) {
1456
1457         CGroupContext *c;
1458         int r;
1459
1460         assert(u);
1461
1462         c = unit_get_cgroup_context(u);
1463         if (!c)
1464                 return 0;
1465
1466         /* Figure out our cgroup path */
1467         r = unit_pick_cgroup_path(u);
1468         if (r < 0)
1469                 return r;
1470
1471         /* First, create our own group */
1472         r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path);
1473         if (r < 0)
1474                 return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path);
1475
1476         /* Start watching it */
1477         (void) unit_watch_cgroup(u);
1478
1479         /* Enable all controllers we need */
1480         r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
1481         if (r < 0)
1482                 log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m", u->cgroup_path);
1483
1484         /* Keep track that this is now realized */
1485         u->cgroup_realized = true;
1486         u->cgroup_realized_mask = target_mask;
1487         u->cgroup_enabled_mask = enable_mask;
1488         u->cgroup_bpf_state = needs_bpf ? UNIT_CGROUP_BPF_ON : UNIT_CGROUP_BPF_OFF;
1489
1490         if (u->type != UNIT_SLICE && !unit_cgroup_delegate(u)) {
1491
1492                 /* Then, possibly move things over, but not if
1493                  * subgroups may contain processes, which is the case
1494                  * for slice and delegation units. */
1495                 r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u);
1496                 if (r < 0)
1497                         log_unit_warning_errno(u, r, "Failed to migrate cgroup from to %s, ignoring: %m", u->cgroup_path);
1498         }
1499
1500         return 0;
1501 }
1502
1503 static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char *suffix_path) {
1504         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1505         char *pp;
1506         int r;
1507
1508         assert(u);
1509
1510         if (MANAGER_IS_SYSTEM(u->manager))
1511                 return -EINVAL;
1512
1513         if (!u->manager->system_bus)
1514                 return -EIO;
1515
1516         if (!u->cgroup_path)
1517                 return -EINVAL;
1518
1519         /* Determine this unit's cgroup path relative to our cgroup root */
1520         pp = path_startswith(u->cgroup_path, u->manager->cgroup_root);
1521         if (!pp)
1522                 return -EINVAL;
1523
1524         pp = strjoina("/", pp, suffix_path);
1525         path_kill_slashes(pp);
1526
1527         r = sd_bus_call_method(u->manager->system_bus,
1528                                "org.freedesktop.systemd1",
1529                                "/org/freedesktop/systemd1",
1530                                "org.freedesktop.systemd1.Manager",
1531                                "AttachProcessesToUnit",
1532                                &error, NULL,
1533                                "ssau",
1534                                NULL /* empty unit name means client's unit, i.e. us */, pp, 1, (uint32_t) pid);
1535         if (r < 0)
1536                 return log_unit_debug_errno(u, r, "Failed to attach unit process " PID_FMT " via the bus: %s", pid, bus_error_message(&error, r));
1537
1538         return 0;
1539 }
1540
1541 int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
1542         CGroupMask delegated_mask;
1543         const char *p;
1544         Iterator i;
1545         void *pidp;
1546         int r, q;
1547
1548         assert(u);
1549
1550         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1551                 return -EINVAL;
1552
1553         if (set_isempty(pids))
1554                 return 0;
1555
1556         r = unit_realize_cgroup(u);
1557         if (r < 0)
1558                 return r;
1559
1560         if (isempty(suffix_path))
1561                 p = u->cgroup_path;
1562         else
1563                 p = strjoina(u->cgroup_path, "/", suffix_path);
1564
1565         delegated_mask = unit_get_delegate_mask(u);
1566
1567         r = 0;
1568         SET_FOREACH(pidp, pids, i) {
1569                 pid_t pid = PTR_TO_PID(pidp);
1570                 CGroupController c;
1571
1572                 /* First, attach the PID to the main cgroup hierarchy */
1573                 q = cg_attach(SYSTEMD_CGROUP_CONTROLLER, p, pid);
1574                 if (q < 0) {
1575                         log_unit_debug_errno(u, q, "Couldn't move process " PID_FMT " to requested cgroup '%s': %m", pid, p);
1576
1577                         if (MANAGER_IS_USER(u->manager) && IN_SET(q, -EPERM, -EACCES)) {
1578                                 int z;
1579
1580                                 /* If we are in a user instance, and we can't move the process ourselves due to
1581                                  * permission problems, let's ask the system instance about it instead. Since it's more
1582                                  * privileged it might be able to move the process across the leaves of a subtree who's
1583                                  * top node is not owned by us. */
1584
1585                                 z = unit_attach_pid_to_cgroup_via_bus(u, pid, suffix_path);
1586                                 if (z < 0)
1587                                         log_unit_debug_errno(u, z, "Couldn't move process " PID_FMT " to requested cgroup '%s' via the system bus either: %m", pid, p);
1588                                 else
1589                                         continue; /* When the bus thing worked via the bus we are fully done for this PID. */
1590                         }
1591
1592                         if (r >= 0)
1593                                 r = q; /* Remember first error */
1594
1595                         continue;
1596                 }
1597
1598                 q = cg_all_unified();
1599                 if (q < 0)
1600                         return q;
1601                 if (q > 0)
1602                         continue;
1603
1604                 /* In the legacy hierarchy, attach the process to the request cgroup if possible, and if not to the
1605                  * innermost realized one */
1606
1607                 for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
1608                         CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
1609                         const char *realized;
1610
1611                         if (!(u->manager->cgroup_supported & bit))
1612                                 continue;
1613
1614                         /* If this controller is delegated and realized, honour the caller's request for the cgroup suffix. */
1615                         if (delegated_mask & u->cgroup_realized_mask & bit) {
1616                                 q = cg_attach(cgroup_controller_to_string(c), p, pid);
1617                                 if (q >= 0)
1618                                         continue; /* Success! */
1619
1620                                 log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to requested cgroup %s in controller %s, falling back to unit's cgroup: %m",
1621                                                      pid, p, cgroup_controller_to_string(c));
1622                         }
1623
1624                         /* So this controller is either not delegate or realized, or something else weird happened. In
1625                          * that case let's attach the PID at least to the closest cgroup up the tree that is
1626                          * realized. */
1627                         realized = unit_get_realized_cgroup_path(u, bit);
1628                         if (!realized)
1629                                 continue; /* Not even realized in the root slice? Then let's not bother */
1630
1631                         q = cg_attach(cgroup_controller_to_string(c), realized, pid);
1632                         if (q < 0)
1633                                 log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to realized cgroup %s in controller %s, ignoring: %m",
1634                                                      pid, realized, cgroup_controller_to_string(c));
1635                 }
1636         }
1637
1638         return r;
1639 }
1640
1641 static void cgroup_xattr_apply(Unit *u) {
1642         char ids[SD_ID128_STRING_MAX];
1643         int r;
1644
1645         assert(u);
1646
1647         if (!MANAGER_IS_SYSTEM(u->manager))
1648                 return;
1649
1650         if (sd_id128_is_null(u->invocation_id))
1651                 return;
1652
1653         r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
1654                          "trusted.invocation_id",
1655                          sd_id128_to_string(u->invocation_id, ids), 32,
1656                          0);
1657         if (r < 0)
1658                 log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path);
1659 }
1660
1661 static bool unit_has_mask_realized(
1662                 Unit *u,
1663                 CGroupMask target_mask,
1664                 CGroupMask enable_mask,
1665                 bool needs_bpf) {
1666
1667         assert(u);
1668
1669         return u->cgroup_realized &&
1670                 u->cgroup_realized_mask == target_mask &&
1671                 u->cgroup_enabled_mask == enable_mask &&
1672                 ((needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_ON) ||
1673                  (!needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_OFF));
1674 }
1675
1676 static void unit_add_to_cgroup_realize_queue(Unit *u) {
1677         assert(u);
1678
1679         if (u->in_cgroup_realize_queue)
1680                 return;
1681
1682         LIST_PREPEND(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
1683         u->in_cgroup_realize_queue = true;
1684 }
1685
1686 static void unit_remove_from_cgroup_realize_queue(Unit *u) {
1687         assert(u);
1688
1689         if (!u->in_cgroup_realize_queue)
1690                 return;
1691
1692         LIST_REMOVE(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
1693         u->in_cgroup_realize_queue = false;
1694 }
1695
1696 /* Check if necessary controllers and attributes for a unit are in place.
1697  *
1698  * If so, do nothing.
1699  * If not, create paths, move processes over, and set attributes.
1700  *
1701  * Returns 0 on success and < 0 on failure. */
1702 static int unit_realize_cgroup_now(Unit *u, ManagerState state) {
1703         CGroupMask target_mask, enable_mask;
1704         bool needs_bpf, apply_bpf;
1705         int r;
1706
1707         assert(u);
1708
1709         unit_remove_from_cgroup_realize_queue(u);
1710
1711         target_mask = unit_get_target_mask(u);
1712         enable_mask = unit_get_enable_mask(u);
1713         needs_bpf = unit_get_needs_bpf(u);
1714
1715         if (unit_has_mask_realized(u, target_mask, enable_mask, needs_bpf))
1716                 return 0;
1717
1718         /* Make sure we apply the BPF filters either when one is configured, or if none is configured but previously
1719          * the state was anything but off. This way, if a unit with a BPF filter applied is reconfigured to lose it
1720          * this will trickle down properly to cgroupfs. */
1721         apply_bpf = needs_bpf || u->cgroup_bpf_state != UNIT_CGROUP_BPF_OFF;
1722
1723         /* First, realize parents */
1724         if (UNIT_ISSET(u->slice)) {
1725                 r = unit_realize_cgroup_now(UNIT_DEREF(u->slice), state);
1726                 if (r < 0)
1727                         return r;
1728         }
1729
1730         /* And then do the real work */
1731         r = unit_create_cgroup(u, target_mask, enable_mask, needs_bpf);
1732         if (r < 0)
1733                 return r;
1734
1735         /* Finally, apply the necessary attributes. */
1736         cgroup_context_apply(u, target_mask, apply_bpf, state);
1737         cgroup_xattr_apply(u);
1738
1739         return 0;
1740 }
1741
1742 unsigned manager_dispatch_cgroup_realize_queue(Manager *m) {
1743         ManagerState state;
1744         unsigned n = 0;
1745         Unit *i;
1746         int r;
1747
1748         assert(m);
1749
1750         state = manager_state(m);
1751
1752         while ((i = m->cgroup_realize_queue)) {
1753                 assert(i->in_cgroup_realize_queue);
1754
1755                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(i))) {
1756                         /* Maybe things changed, and the unit is not actually active anymore? */
1757                         unit_remove_from_cgroup_realize_queue(i);
1758                         continue;
1759                 }
1760
1761                 r = unit_realize_cgroup_now(i, state);
1762                 if (r < 0)
1763                         log_warning_errno(r, "Failed to realize cgroups for queued unit %s, ignoring: %m", i->id);
1764
1765                 n++;
1766         }
1767
1768         return n;
1769 }
1770
1771 static void unit_add_siblings_to_cgroup_realize_queue(Unit *u) {
1772         Unit *slice;
1773
1774         /* This adds the siblings of the specified unit and the
1775          * siblings of all parent units to the cgroup queue. (But
1776          * neither the specified unit itself nor the parents.) */
1777
1778         while ((slice = UNIT_DEREF(u->slice))) {
1779                 Iterator i;
1780                 Unit *m;
1781                 void *v;
1782
1783                 HASHMAP_FOREACH_KEY(v, m, u->dependencies[UNIT_BEFORE], i) {
1784                         if (m == u)
1785                                 continue;
1786
1787                         /* Skip units that have a dependency on the slice
1788                          * but aren't actually in it. */
1789                         if (UNIT_DEREF(m->slice) != slice)
1790                                 continue;
1791
1792                         /* No point in doing cgroup application for units
1793                          * without active processes. */
1794                         if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(m)))
1795                                 continue;
1796
1797                         /* If the unit doesn't need any new controllers
1798                          * and has current ones realized, it doesn't need
1799                          * any changes. */
1800                         if (unit_has_mask_realized(m,
1801                                                    unit_get_target_mask(m),
1802                                                    unit_get_enable_mask(m),
1803                                                    unit_get_needs_bpf(m)))
1804                                 continue;
1805
1806                         unit_add_to_cgroup_realize_queue(m);
1807                 }
1808
1809                 u = slice;
1810         }
1811 }
1812
1813 int unit_realize_cgroup(Unit *u) {
1814         assert(u);
1815
1816         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1817                 return 0;
1818
1819         /* So, here's the deal: when realizing the cgroups for this
1820          * unit, we need to first create all parents, but there's more
1821          * actually: for the weight-based controllers we also need to
1822          * make sure that all our siblings (i.e. units that are in the
1823          * same slice as we are) have cgroups, too. Otherwise, things
1824          * would become very uneven as each of their processes would
1825          * get as much resources as all our group together. This call
1826          * will synchronously create the parent cgroups, but will
1827          * defer work on the siblings to the next event loop
1828          * iteration. */
1829
1830         /* Add all sibling slices to the cgroup queue. */
1831         unit_add_siblings_to_cgroup_realize_queue(u);
1832
1833         /* And realize this one now (and apply the values) */
1834         return unit_realize_cgroup_now(u, manager_state(u->manager));
1835 }
1836
1837 void unit_release_cgroup(Unit *u) {
1838         assert(u);
1839
1840         /* Forgets all cgroup details for this cgroup */
1841
1842         if (u->cgroup_path) {
1843                 (void) hashmap_remove(u->manager->cgroup_unit, u->cgroup_path);
1844                 u->cgroup_path = mfree(u->cgroup_path);
1845         }
1846
1847         if (u->cgroup_inotify_wd >= 0) {
1848                 if (inotify_rm_watch(u->manager->cgroup_inotify_fd, u->cgroup_inotify_wd) < 0)
1849                         log_unit_debug_errno(u, errno, "Failed to remove cgroup inotify watch %i for %s, ignoring", u->cgroup_inotify_wd, u->id);
1850
1851                 (void) hashmap_remove(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd));
1852                 u->cgroup_inotify_wd = -1;
1853         }
1854 }
1855
1856 void unit_prune_cgroup(Unit *u) {
1857         int r;
1858         bool is_root_slice;
1859
1860         assert(u);
1861
1862         /* Removes the cgroup, if empty and possible, and stops watching it. */
1863
1864         if (!u->cgroup_path)
1865                 return;
1866
1867         (void) unit_get_cpu_usage(u, NULL); /* Cache the last CPU usage value before we destroy the cgroup */
1868
1869         is_root_slice = unit_has_name(u, SPECIAL_ROOT_SLICE);
1870
1871         r = cg_trim_everywhere(u->manager->cgroup_supported, u->cgroup_path, !is_root_slice);
1872         if (r < 0) {
1873                 log_unit_debug_errno(u, r, "Failed to destroy cgroup %s, ignoring: %m", u->cgroup_path);
1874                 return;
1875         }
1876
1877         if (is_root_slice)
1878                 return;
1879
1880         unit_release_cgroup(u);
1881
1882         u->cgroup_realized = false;
1883         u->cgroup_realized_mask = 0;
1884         u->cgroup_enabled_mask = 0;
1885 }
1886
1887 int unit_search_main_pid(Unit *u, pid_t *ret) {
1888         _cleanup_fclose_ FILE *f = NULL;
1889         pid_t pid = 0, npid, mypid;
1890         int r;
1891
1892         assert(u);
1893         assert(ret);
1894
1895         if (!u->cgroup_path)
1896                 return -ENXIO;
1897
1898         r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, &f);
1899         if (r < 0)
1900                 return r;
1901
1902         mypid = getpid_cached();
1903         while (cg_read_pid(f, &npid) > 0)  {
1904                 pid_t ppid;
1905
1906                 if (npid == pid)
1907                         continue;
1908
1909                 /* Ignore processes that aren't our kids */
1910                 if (get_process_ppid(npid, &ppid) >= 0 && ppid != mypid)
1911                         continue;
1912
1913                 if (pid != 0)
1914                         /* Dang, there's more than one daemonized PID
1915                         in this group, so we don't know what process
1916                         is the main process. */
1917
1918                         return -ENODATA;
1919
1920                 pid = npid;
1921         }
1922
1923         *ret = pid;
1924         return 0;
1925 }
1926
1927 static int unit_watch_pids_in_path(Unit *u, const char *path) {
1928         _cleanup_closedir_ DIR *d = NULL;
1929         _cleanup_fclose_ FILE *f = NULL;
1930         int ret = 0, r;
1931
1932         assert(u);
1933         assert(path);
1934
1935         r = cg_enumerate_processes(SYSTEMD_CGROUP_CONTROLLER, path, &f);
1936         if (r < 0)
1937                 ret = r;
1938         else {
1939                 pid_t pid;
1940
1941                 while ((r = cg_read_pid(f, &pid)) > 0) {
1942                         r = unit_watch_pid(u, pid);
1943                         if (r < 0 && ret >= 0)
1944                                 ret = r;
1945                 }
1946
1947                 if (r < 0 && ret >= 0)
1948                         ret = r;
1949         }
1950
1951         r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, path, &d);
1952         if (r < 0) {
1953                 if (ret >= 0)
1954                         ret = r;
1955         } else {
1956                 char *fn;
1957
1958                 while ((r = cg_read_subgroup(d, &fn)) > 0) {
1959                         _cleanup_free_ char *p = NULL;
1960
1961                         p = strjoin(path, "/", fn);
1962                         free(fn);
1963
1964                         if (!p)
1965                                 return -ENOMEM;
1966
1967                         r = unit_watch_pids_in_path(u, p);
1968                         if (r < 0 && ret >= 0)
1969                                 ret = r;
1970                 }
1971
1972                 if (r < 0 && ret >= 0)
1973                         ret = r;
1974         }
1975
1976         return ret;
1977 }
1978
1979 int unit_synthesize_cgroup_empty_event(Unit *u) {
1980         int r;
1981
1982         assert(u);
1983
1984         /* Enqueue a synthetic cgroup empty event if this unit doesn't watch any PIDs anymore. This is compatibility
1985          * support for non-unified systems where notifications aren't reliable, and hence need to take whatever we can
1986          * get as notification source as soon as we stopped having any useful PIDs to watch for. */
1987
1988         if (!u->cgroup_path)
1989                 return -ENOENT;
1990
1991         r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
1992         if (r < 0)
1993                 return r;
1994         if (r > 0) /* On unified we have reliable notifications, and don't need this */
1995                 return 0;
1996
1997         if (!set_isempty(u->pids))
1998                 return 0;
1999
2000         unit_add_to_cgroup_empty_queue(u);
2001         return 0;
2002 }
2003
2004 int unit_watch_all_pids(Unit *u) {
2005         int r;
2006
2007         assert(u);
2008
2009         /* Adds all PIDs from our cgroup to the set of PIDs we
2010          * watch. This is a fallback logic for cases where we do not
2011          * get reliable cgroup empty notifications: we try to use
2012          * SIGCHLD as replacement. */
2013
2014         if (!u->cgroup_path)
2015                 return -ENOENT;
2016
2017         r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
2018         if (r < 0)
2019                 return r;
2020         if (r > 0) /* On unified we can use proper notifications */
2021                 return 0;
2022
2023         return unit_watch_pids_in_path(u, u->cgroup_path);
2024 }
2025
2026 static int on_cgroup_empty_event(sd_event_source *s, void *userdata) {
2027         Manager *m = userdata;
2028         Unit *u;
2029         int r;
2030
2031         assert(s);
2032         assert(m);
2033
2034         u = m->cgroup_empty_queue;
2035         if (!u)
2036                 return 0;
2037
2038         assert(u->in_cgroup_empty_queue);
2039         u->in_cgroup_empty_queue = false;
2040         LIST_REMOVE(cgroup_empty_queue, m->cgroup_empty_queue, u);
2041
2042         if (m->cgroup_empty_queue) {
2043                 /* More stuff queued, let's make sure we remain enabled */
2044                 r = sd_event_source_set_enabled(s, SD_EVENT_ONESHOT);
2045                 if (r < 0)
2046                         log_debug_errno(r, "Failed to reenable cgroup empty event source: %m");
2047         }
2048
2049         unit_add_to_gc_queue(u);
2050
2051         if (UNIT_VTABLE(u)->notify_cgroup_empty)
2052                 UNIT_VTABLE(u)->notify_cgroup_empty(u);
2053
2054         return 0;
2055 }
2056
2057 void unit_add_to_cgroup_empty_queue(Unit *u) {
2058         int r;
2059
2060         assert(u);
2061
2062         /* Note that there are four different ways how cgroup empty events reach us:
2063          *
2064          * 1. On the unified hierarchy we get an inotify event on the cgroup
2065          *
2066          * 2. On the legacy hierarchy, when running in system mode, we get a datagram on the cgroup agent socket
2067          *
2068          * 3. On the legacy hierarchy, when running in user mode, we get a D-Bus signal on the system bus
2069          *
2070          * 4. On the legacy hierarchy, in service units we start watching all processes of the cgroup for SIGCHLD as
2071          *    soon as we get one SIGCHLD, to deal with unreliable cgroup notifications.
2072          *
2073          * Regardless which way we got the notification, we'll verify it here, and then add it to a separate
2074          * queue. This queue will be dispatched at a lower priority than the SIGCHLD handler, so that we always use
2075          * SIGCHLD if we can get it first, and only use the cgroup empty notifications if there's no SIGCHLD pending
2076          * (which might happen if the cgroup doesn't contain processes that are our own child, which is typically the
2077          * case for scope units). */
2078
2079         if (u->in_cgroup_empty_queue)
2080                 return;
2081
2082         /* Let's verify that the cgroup is really empty */
2083         if (!u->cgroup_path)
2084                 return;
2085         r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
2086         if (r < 0) {
2087                 log_unit_debug_errno(u, r, "Failed to determine whether cgroup %s is empty: %m", u->cgroup_path);
2088                 return;
2089         }
2090         if (r == 0)
2091                 return;
2092
2093         LIST_PREPEND(cgroup_empty_queue, u->manager->cgroup_empty_queue, u);
2094         u->in_cgroup_empty_queue = true;
2095
2096         /* Trigger the defer event */
2097         r = sd_event_source_set_enabled(u->manager->cgroup_empty_event_source, SD_EVENT_ONESHOT);
2098         if (r < 0)
2099                 log_debug_errno(r, "Failed to enable cgroup empty event source: %m");
2100 }
2101
2102 static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
2103         Manager *m = userdata;
2104
2105         assert(s);
2106         assert(fd >= 0);
2107         assert(m);
2108
2109         for (;;) {
2110                 union inotify_event_buffer buffer;
2111                 struct inotify_event *e;
2112                 ssize_t l;
2113
2114                 l = read(fd, &buffer, sizeof(buffer));
2115                 if (l < 0) {
2116                         if (IN_SET(errno, EINTR, EAGAIN))
2117                                 return 0;
2118
2119                         return log_error_errno(errno, "Failed to read control group inotify events: %m");
2120                 }
2121
2122                 FOREACH_INOTIFY_EVENT(e, buffer, l) {
2123                         Unit *u;
2124
2125                         if (e->wd < 0)
2126                                 /* Queue overflow has no watch descriptor */
2127                                 continue;
2128
2129                         if (e->mask & IN_IGNORED)
2130                                 /* The watch was just removed */
2131                                 continue;
2132
2133                         u = hashmap_get(m->cgroup_inotify_wd_unit, INT_TO_PTR(e->wd));
2134                         if (!u) /* Not that inotify might deliver
2135                                  * events for a watch even after it
2136                                  * was removed, because it was queued
2137                                  * before the removal. Let's ignore
2138                                  * this here safely. */
2139                                 continue;
2140
2141                         unit_add_to_cgroup_empty_queue(u);
2142                 }
2143         }
2144 }
2145 #endif // 0
2146
2147 int manager_setup_cgroup(Manager *m) {
2148         _cleanup_free_ char *path = NULL;
2149         const char *scope_path;
2150         CGroupController c;
2151         int r, all_unified;
2152 #if 0 /// UNNEEDED by elogind
2153         char *e;
2154 #endif // 0
2155
2156         assert(m);
2157
2158         /* 1. Determine hierarchy */
2159         m->cgroup_root = mfree(m->cgroup_root);
2160 #if 0 /// elogind is not init and must therefore search for PID 1 instead of self.
2161         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &m->cgroup_root);
2162 #else
2163         r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 1, &m->cgroup_root);
2164 #endif // 0
2165         if (r < 0)
2166                 return log_error_errno(r, "Cannot determine cgroup we are running in: %m");
2167
2168 #if 0 /// elogind does not support systemd scopes and slices
2169         /* Chop off the init scope, if we are already located in it */
2170         e = endswith(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
2171
2172         /* LEGACY: Also chop off the system slice if we are in
2173          * it. This is to support live upgrades from older systemd
2174          * versions where PID 1 was moved there. Also see
2175          * cg_get_root_path(). */
2176         if (!e && MANAGER_IS_SYSTEM(m)) {
2177                 e = endswith(m->cgroup_root, "/" SPECIAL_SYSTEM_SLICE);
2178                 if (!e)
2179                         e = endswith(m->cgroup_root, "/system"); /* even more legacy */
2180         }
2181         if (e)
2182                 *e = 0;
2183 #endif // 0
2184
2185         log_debug_elogind("Cgroup Controller \"%s\" -> root \"%s\"",
2186                           SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root);
2187         /* And make sure to store away the root value without trailing slash, even for the root dir, so that we can
2188          * easily prepend it everywhere. */
2189         delete_trailing_chars(m->cgroup_root, "/");
2190
2191         /* 2. Show data */
2192         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, NULL, &path);
2193         if (r < 0)
2194                 return log_error_errno(r, "Cannot find cgroup mount point: %m");
2195
2196         r = cg_unified_flush();
2197         if (r < 0)
2198                 return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m");
2199
2200         all_unified = cg_all_unified();
2201         if (all_unified < 0)
2202                 return log_error_errno(all_unified, "Couldn't determine whether we are in all unified mode: %m");
2203         if (all_unified > 0)
2204                 log_debug("Unified cgroup hierarchy is located at %s.", path);
2205         else {
2206                 r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
2207                 if (r < 0)
2208                         return log_error_errno(r, "Failed to determine whether systemd's own controller is in unified mode: %m");
2209                 if (r > 0)
2210                         log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path);
2211                 else
2212                         log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER_LEGACY ". File system hierarchy is at %s.", path);
2213         }
2214
2215 #if 0 /// elogind is not init, and does not install the agent here.
2216         /* 3. Allocate cgroup empty defer event source */
2217         m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source);
2218         r = sd_event_add_defer(m->event, &m->cgroup_empty_event_source, on_cgroup_empty_event, m);
2219         if (r < 0)
2220                 return log_error_errno(r, "Failed to create cgroup empty event source: %m");
2221
2222         r = sd_event_source_set_priority(m->cgroup_empty_event_source, SD_EVENT_PRIORITY_NORMAL-5);
2223         if (r < 0)
2224                 return log_error_errno(r, "Failed to set priority of cgroup empty event source: %m");
2225
2226         r = sd_event_source_set_enabled(m->cgroup_empty_event_source, SD_EVENT_OFF);
2227         if (r < 0)
2228                 return log_error_errno(r, "Failed to disable cgroup empty event source: %m");
2229
2230         (void) sd_event_source_set_description(m->cgroup_empty_event_source, "cgroup-empty");
2231
2232         /* 4. Install notifier inotify object, or agent */
2233         if (cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER) > 0) {
2234
2235                 /* In the unified hierarchy we can get cgroup empty notifications via inotify. */
2236
2237                 m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
2238                 safe_close(m->cgroup_inotify_fd);
2239
2240                 m->cgroup_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC);
2241                 if (m->cgroup_inotify_fd < 0)
2242                         return log_error_errno(errno, "Failed to create control group inotify object: %m");
2243
2244                 r = sd_event_add_io(m->event, &m->cgroup_inotify_event_source, m->cgroup_inotify_fd, EPOLLIN, on_cgroup_inotify_event, m);
2245                 if (r < 0)
2246                         return log_error_errno(r, "Failed to watch control group inotify object: %m");
2247
2248                 /* Process cgroup empty notifications early, but after service notifications and SIGCHLD. Also
2249                  * see handling of cgroup agent notifications, for the classic cgroup hierarchy support. */
2250                 r = sd_event_source_set_priority(m->cgroup_inotify_event_source, SD_EVENT_PRIORITY_NORMAL-4);
2251                 if (r < 0)
2252                         return log_error_errno(r, "Failed to set priority of inotify event source: %m");
2253
2254                 (void) sd_event_source_set_description(m->cgroup_inotify_event_source, "cgroup-inotify");
2255
2256         } else if (MANAGER_IS_SYSTEM(m) && m->test_run_flags == 0) {
2257
2258                 /* On the legacy hierarchy we only get notifications via cgroup agents. (Which isn't really reliable,
2259                  * since it does not generate events when control groups with children run empty. */
2260
2261                 r = cg_install_release_agent(SYSTEMD_CGROUP_CONTROLLER, SYSTEMD_CGROUP_AGENT_PATH);
2262                 if (r < 0)
2263                         log_warning_errno(r, "Failed to install release agent, ignoring: %m");
2264                 else if (r > 0)
2265                         log_debug("Installed release agent.");
2266                 else if (r == 0)
2267                         log_debug("Release agent already installed.");
2268         }
2269
2270         /* 5. Make sure we are in the special "init.scope" unit in the root slice. */
2271         scope_path = strjoina(m->cgroup_root, "/" SPECIAL_INIT_SCOPE);
2272         r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2273         if (r >= 0) {
2274                 /* Also, move all other userspace processes remaining in the root cgroup into that scope. */
2275                 r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2276                 if (r < 0)
2277                         log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
2278 #else
2279         /* Note:
2280                 * This method is in core, and normally called by systemd
2281                 * being init. As elogind is never init, we can not install
2282                 * our agent here. We do so when mounting our cgroup file
2283                 * system, so only if elogind is its own tiny controller.
2284                 * Further, elogind is not meant to run in systemd init scope. */
2285         if (MANAGER_IS_SYSTEM(m))
2286                 // we are our own cgroup controller
2287                 scope_path = strjoina("");
2288         else if (streq(m->cgroup_root, "/elogind"))
2289                 // root already is our cgroup
2290                 scope_path = strjoina(m->cgroup_root);
2291         else
2292                 // we have to create our own group
2293                 scope_path = strjoina(m->cgroup_root, "/elogind");
2294         r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2295 #endif // 0
2296         log_debug_elogind("Created control group \"%s\"", scope_path);
2297
2298                 /* 6. And pin it, so that it cannot be unmounted */
2299                 safe_close(m->pin_cgroupfs_fd);
2300                 m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
2301                 if (m->pin_cgroupfs_fd < 0)
2302                         return log_error_errno(errno, "Failed to open pin file: %m");
2303
2304 #if 0 /// this is from the cgroup migration above that elogind does not need.
2305         } else if (r < 0 && !m->test_run_flags)
2306                 return log_error_errno(r, "Failed to create %s control group: %m", scope_path);
2307 #endif // 0
2308
2309         /* 7. Always enable hierarchical support if it exists... */
2310         if (!all_unified && m->test_run_flags == 0)
2311                 (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
2312
2313         /* 8. Figure out which controllers are supported, and log about it */
2314         r = cg_mask_supported(&m->cgroup_supported);
2315         if (r < 0)
2316                 return log_error_errno(r, "Failed to determine supported controllers: %m");
2317         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
2318                 log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & CGROUP_CONTROLLER_TO_MASK(c)));
2319
2320         return 0;
2321 }
2322
2323 void manager_shutdown_cgroup(Manager *m, bool delete) {
2324         assert(m);
2325
2326 #if 0 /// elogind is not init
2327         /* We can't really delete the group, since we are in it. But
2328          * let's trim it. */
2329         if (delete && m->cgroup_root && m->test_run_flags != MANAGER_TEST_RUN_MINIMAL)
2330                 (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
2331
2332         m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source);
2333
2334         m->cgroup_inotify_wd_unit = hashmap_free(m->cgroup_inotify_wd_unit);
2335
2336         m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
2337         m->cgroup_inotify_fd = safe_close(m->cgroup_inotify_fd);
2338 #endif // 0
2339
2340         m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd);
2341
2342         m->cgroup_root = mfree(m->cgroup_root);
2343 }
2344
2345 #if 0 /// UNNEEDED by elogind
2346 Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
2347         char *p;
2348         Unit *u;
2349
2350         assert(m);
2351         assert(cgroup);
2352
2353         u = hashmap_get(m->cgroup_unit, cgroup);
2354         if (u)
2355                 return u;
2356
2357         p = strdupa(cgroup);
2358         for (;;) {
2359                 char *e;
2360
2361                 e = strrchr(p, '/');
2362                 if (!e || e == p)
2363                         return hashmap_get(m->cgroup_unit, SPECIAL_ROOT_SLICE);
2364
2365                 *e = 0;
2366
2367                 u = hashmap_get(m->cgroup_unit, p);
2368                 if (u)
2369                         return u;
2370         }
2371 }
2372
2373 Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) {
2374         _cleanup_free_ char *cgroup = NULL;
2375
2376         assert(m);
2377
2378         if (!pid_is_valid(pid))
2379                 return NULL;
2380
2381         if (cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup) < 0)
2382                 return NULL;
2383
2384         return manager_get_unit_by_cgroup(m, cgroup);
2385 }
2386
2387 Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
2388         Unit *u, **array;
2389
2390         assert(m);
2391
2392         /* Note that a process might be owned by multiple units, we return only one here, which is good enough for most
2393          * cases, though not strictly correct. We prefer the one reported by cgroup membership, as that's the most
2394          * relevant one as children of the process will be assigned to that one, too, before all else. */
2395
2396         if (!pid_is_valid(pid))
2397                 return NULL;
2398
2399         if (pid == getpid_cached())
2400                 return hashmap_get(m->units, SPECIAL_INIT_SCOPE);
2401
2402         u = manager_get_unit_by_pid_cgroup(m, pid);
2403         if (u)
2404                 return u;
2405
2406         u = hashmap_get(m->watch_pids, PID_TO_PTR(pid));
2407         if (u)
2408                 return u;
2409
2410         array = hashmap_get(m->watch_pids, PID_TO_PTR(-pid));
2411         if (array)
2412                 return array[0];
2413
2414         return NULL;
2415 }
2416 #endif // 0
2417
2418 #if 0 /// elogind must substitute this with its own variant
2419 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
2420         Unit *u;
2421
2422         assert(m);
2423         assert(cgroup);
2424
2425         /* Called on the legacy hierarchy whenever we get an explicit cgroup notification from the cgroup agent process
2426          * or from the --system instance */
2427
2428         log_debug("Got cgroup empty notification for: %s", cgroup);
2429
2430         u = manager_get_unit_by_cgroup(m, cgroup);
2431         if (!u)
2432                 return 0;
2433
2434         unit_add_to_cgroup_empty_queue(u);
2435         return 1;
2436 }
2437 #else
2438 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
2439         Session *s;
2440
2441         assert(m);
2442         assert(cgroup);
2443
2444         log_debug("Got cgroup empty notification for: %s", cgroup);
2445
2446         s = hashmap_get(m->sessions, cgroup);
2447
2448         if (s) {
2449                 session_finalize(s);
2450                 session_free(s);
2451         } else
2452                 log_warning("Session not found: %s", cgroup);
2453
2454         return 0;
2455 }
2456 #endif // 0
2457 #if 0 /// UNNEEDED by elogind
2458 int unit_get_memory_current(Unit *u, uint64_t *ret) {
2459         _cleanup_free_ char *v = NULL;
2460         int r;
2461
2462         assert(u);
2463         assert(ret);
2464
2465         if (!UNIT_CGROUP_BOOL(u, memory_accounting))
2466                 return -ENODATA;
2467
2468         if (!u->cgroup_path)
2469                 return -ENODATA;
2470
2471         /* The root cgroup doesn't expose this information, let's get it from /proc instead */
2472         if (unit_has_root_cgroup(u))
2473                 return procfs_memory_get_current(ret);
2474
2475         if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
2476                 return -ENODATA;
2477
2478         r = cg_all_unified();
2479         if (r < 0)
2480                 return r;
2481         if (r > 0)
2482                 r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v);
2483         else
2484                 r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
2485         if (r == -ENOENT)
2486                 return -ENODATA;
2487         if (r < 0)
2488                 return r;
2489
2490         return safe_atou64(v, ret);
2491 }
2492
2493 int unit_get_tasks_current(Unit *u, uint64_t *ret) {
2494         _cleanup_free_ char *v = NULL;
2495         int r;
2496
2497         assert(u);
2498         assert(ret);
2499
2500         if (!UNIT_CGROUP_BOOL(u, tasks_accounting))
2501                 return -ENODATA;
2502
2503         if (!u->cgroup_path)
2504                 return -ENODATA;
2505
2506         /* The root cgroup doesn't expose this information, let's get it from /proc instead */
2507         if (unit_has_root_cgroup(u))
2508                 return procfs_tasks_get_current(ret);
2509
2510         if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
2511                 return -ENODATA;
2512
2513         r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v);
2514         if (r == -ENOENT)
2515                 return -ENODATA;
2516         if (r < 0)
2517                 return r;
2518
2519         return safe_atou64(v, ret);
2520 }
2521
2522 static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
2523         _cleanup_free_ char *v = NULL;
2524         uint64_t ns;
2525         int r;
2526
2527         assert(u);
2528         assert(ret);
2529
2530         if (!u->cgroup_path)
2531                 return -ENODATA;
2532
2533         /* The root cgroup doesn't expose this information, let's get it from /proc instead */
2534         if (unit_has_root_cgroup(u))
2535                 return procfs_cpu_get_usage(ret);
2536
2537         r = cg_all_unified();
2538         if (r < 0)
2539                 return r;
2540         if (r > 0) {
2541                 _cleanup_free_ char *val = NULL;
2542                 uint64_t us;
2543
2544                 if ((u->cgroup_realized_mask & CGROUP_MASK_CPU) == 0)
2545                         return -ENODATA;
2546
2547                 r = cg_get_keyed_attribute("cpu", u->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
2548                 if (r < 0)
2549                         return r;
2550                 if (IN_SET(r, -ENOENT, -ENXIO))
2551                         return -ENODATA;
2552
2553                 r = safe_atou64(val, &us);
2554                 if (r < 0)
2555                         return r;
2556
2557                 ns = us * NSEC_PER_USEC;
2558         } else {
2559                 if ((u->cgroup_realized_mask & CGROUP_MASK_CPUACCT) == 0)
2560                         return -ENODATA;
2561
2562                 r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v);
2563                 if (r == -ENOENT)
2564                         return -ENODATA;
2565                 if (r < 0)
2566                         return r;
2567
2568                 r = safe_atou64(v, &ns);
2569                 if (r < 0)
2570                         return r;
2571         }
2572
2573         *ret = ns;
2574         return 0;
2575 }
2576
2577 int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
2578         nsec_t ns;
2579         int r;
2580
2581         assert(u);
2582
2583         /* Retrieve the current CPU usage counter. This will subtract the CPU counter taken when the unit was
2584          * started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply
2585          * call this function with a NULL return value. */
2586
2587         if (!UNIT_CGROUP_BOOL(u, cpu_accounting))
2588                 return -ENODATA;
2589
2590         r = unit_get_cpu_usage_raw(u, &ns);
2591         if (r == -ENODATA && u->cpu_usage_last != NSEC_INFINITY) {
2592                 /* If we can't get the CPU usage anymore (because the cgroup was already removed, for example), use our
2593                  * cached value. */
2594
2595                 if (ret)
2596                         *ret = u->cpu_usage_last;
2597                 return 0;
2598         }
2599         if (r < 0)
2600                 return r;
2601
2602         if (ns > u->cpu_usage_base)
2603                 ns -= u->cpu_usage_base;
2604         else
2605                 ns = 0;
2606
2607         u->cpu_usage_last = ns;
2608         if (ret)
2609                 *ret = ns;
2610
2611         return 0;
2612 }
2613
2614 int unit_get_ip_accounting(
2615                 Unit *u,
2616                 CGroupIPAccountingMetric metric,
2617                 uint64_t *ret) {
2618
2619         uint64_t value;
2620         int fd, r;
2621
2622         assert(u);
2623         assert(metric >= 0);
2624         assert(metric < _CGROUP_IP_ACCOUNTING_METRIC_MAX);
2625         assert(ret);
2626
2627         if (!UNIT_CGROUP_BOOL(u, ip_accounting))
2628                 return -ENODATA;
2629
2630         fd = IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_INGRESS_PACKETS) ?
2631                 u->ip_accounting_ingress_map_fd :
2632                 u->ip_accounting_egress_map_fd;
2633         if (fd < 0)
2634                 return -ENODATA;
2635
2636         if (IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_EGRESS_BYTES))
2637                 r = bpf_firewall_read_accounting(fd, &value, NULL);
2638         else
2639                 r = bpf_firewall_read_accounting(fd, NULL, &value);
2640         if (r < 0)
2641                 return r;
2642
2643         /* Add in additional metrics from a previous runtime. Note that when reexecing/reloading the daemon we compile
2644          * all BPF programs and maps anew, but serialize the old counters. When deserializing we store them in the
2645          * ip_accounting_extra[] field, and add them in here transparently. */
2646
2647         *ret = value + u->ip_accounting_extra[metric];
2648
2649         return r;
2650 }
2651
2652 int unit_reset_cpu_accounting(Unit *u) {
2653         nsec_t ns;
2654         int r;
2655
2656         assert(u);
2657
2658         u->cpu_usage_last = NSEC_INFINITY;
2659
2660         r = unit_get_cpu_usage_raw(u, &ns);
2661         if (r < 0) {
2662                 u->cpu_usage_base = 0;
2663                 return r;
2664         }
2665
2666         u->cpu_usage_base = ns;
2667         return 0;
2668 }
2669
2670 int unit_reset_ip_accounting(Unit *u) {
2671         int r = 0, q = 0;
2672
2673         assert(u);
2674
2675         if (u->ip_accounting_ingress_map_fd >= 0)
2676                 r = bpf_firewall_reset_accounting(u->ip_accounting_ingress_map_fd);
2677
2678         if (u->ip_accounting_egress_map_fd >= 0)
2679                 q = bpf_firewall_reset_accounting(u->ip_accounting_egress_map_fd);
2680
2681         zero(u->ip_accounting_extra);
2682
2683         return r < 0 ? r : q;
2684 }
2685
2686 void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
2687         assert(u);
2688
2689         if (!UNIT_HAS_CGROUP_CONTEXT(u))
2690                 return;
2691
2692         if (m == 0)
2693                 return;
2694
2695         /* always invalidate compat pairs together */
2696         if (m & (CGROUP_MASK_IO | CGROUP_MASK_BLKIO))
2697                 m |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
2698
2699         if (m & (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT))
2700                 m |= CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT;
2701
2702         if ((u->cgroup_realized_mask & m) == 0) /* NOP? */
2703                 return;
2704
2705         u->cgroup_realized_mask &= ~m;
2706         unit_add_to_cgroup_realize_queue(u);
2707 }
2708
2709 void unit_invalidate_cgroup_bpf(Unit *u) {
2710         assert(u);
2711
2712         if (!UNIT_HAS_CGROUP_CONTEXT(u))
2713                 return;
2714
2715         if (u->cgroup_bpf_state == UNIT_CGROUP_BPF_INVALIDATED) /* NOP? */
2716                 return;
2717
2718         u->cgroup_bpf_state = UNIT_CGROUP_BPF_INVALIDATED;
2719         unit_add_to_cgroup_realize_queue(u);
2720
2721         /* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access
2722          * list of our children includes our own. */
2723         if (u->type == UNIT_SLICE) {
2724                 Unit *member;
2725                 Iterator i;
2726                 void *v;
2727
2728                 HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
2729                         if (member == u)
2730                                 continue;
2731
2732                         if (UNIT_DEREF(member->slice) != u)
2733                                 continue;
2734
2735                         unit_invalidate_cgroup_bpf(member);
2736                 }
2737         }
2738 }
2739
2740 bool unit_cgroup_delegate(Unit *u) {
2741         CGroupContext *c;
2742
2743         assert(u);
2744
2745         if (!UNIT_VTABLE(u)->can_delegate)
2746                 return false;
2747
2748         c = unit_get_cgroup_context(u);
2749         if (!c)
2750                 return false;
2751
2752         return c->delegate;
2753 }
2754
2755 void manager_invalidate_startup_units(Manager *m) {
2756         Iterator i;
2757         Unit *u;
2758
2759         assert(m);
2760
2761         SET_FOREACH(u, m->startup_units, i)
2762                 unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO);
2763 }
2764
2765 static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
2766         [CGROUP_AUTO] = "auto",
2767         [CGROUP_CLOSED] = "closed",
2768         [CGROUP_STRICT] = "strict",
2769 };
2770
2771 DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
2772 #endif // 0