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