chiark / gitweb /
bpf: use BPF_F_ALLOW_MULTI flag if it is available
[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   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <fcntl.h>
22 #include <fnmatch.h>
23
24 #include "alloc-util.h"
25 //#include "blockdev-util.h"
26 //#include "bpf-firewall.h"
27 //#include "bus-error.h"
28 #include "cgroup-util.h"
29 #include "cgroup.h"
30 #include "fd-util.h"
31 #include "fileio.h"
32 #include "fs-util.h"
33 #include "parse-util.h"
34 #include "path-util.h"
35 #include "process-util.h"
36 //#include "procfs-util.h"
37 //#include "special.h"
38 #include "stdio-util.h"
39 #include "string-table.h"
40 #include "string-util.h"
41
42 #define CGROUP_CPU_QUOTA_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
43
44 bool unit_has_root_cgroup(Unit *u) {
45         assert(u);
46
47         /* Returns whether this unit manages the root cgroup. Note that this is different from being named "-.slice",
48          * as inside of containers the root slice won't be identical to the root cgroup. */
49
50         if (!u->cgroup_path)
51                 return false;
52
53         return isempty(u->cgroup_path) || path_equal(u->cgroup_path, "/");
54 }
55
56 #if 0 /// UNNEEDED by elogind
57 static void cgroup_compat_warn(void) {
58         static bool cgroup_compat_warned = false;
59
60         if (cgroup_compat_warned)
61                 return;
62
63         log_warning("cgroup compatibility translation between legacy and unified hierarchy settings activated. See cgroup-compat debug messages for details.");
64         cgroup_compat_warned = true;
65 }
66
67 #define log_cgroup_compat(unit, fmt, ...) do {                                  \
68                 cgroup_compat_warn();                                           \
69                 log_unit_debug(unit, "cgroup-compat: " fmt, ##__VA_ARGS__);     \
70         } while (false)
71
72 void cgroup_context_init(CGroupContext *c) {
73         assert(c);
74
75         /* Initialize everything to the kernel defaults, assuming the
76          * structure is preinitialized to 0 */
77
78         c->cpu_weight = CGROUP_WEIGHT_INVALID;
79         c->startup_cpu_weight = CGROUP_WEIGHT_INVALID;
80         c->cpu_quota_per_sec_usec = USEC_INFINITY;
81
82         c->cpu_shares = CGROUP_CPU_SHARES_INVALID;
83         c->startup_cpu_shares = CGROUP_CPU_SHARES_INVALID;
84
85         c->memory_high = CGROUP_LIMIT_MAX;
86         c->memory_max = CGROUP_LIMIT_MAX;
87         c->memory_swap_max = CGROUP_LIMIT_MAX;
88
89         c->memory_limit = CGROUP_LIMIT_MAX;
90
91         c->io_weight = CGROUP_WEIGHT_INVALID;
92         c->startup_io_weight = CGROUP_WEIGHT_INVALID;
93
94         c->blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
95         c->startup_blockio_weight = CGROUP_BLKIO_WEIGHT_INVALID;
96
97         c->tasks_max = (uint64_t) -1;
98 }
99
100 void cgroup_context_free_device_allow(CGroupContext *c, CGroupDeviceAllow *a) {
101         assert(c);
102         assert(a);
103
104         LIST_REMOVE(device_allow, c->device_allow, a);
105         free(a->path);
106         free(a);
107 }
108
109 void cgroup_context_free_io_device_weight(CGroupContext *c, CGroupIODeviceWeight *w) {
110         assert(c);
111         assert(w);
112
113         LIST_REMOVE(device_weights, c->io_device_weights, w);
114         free(w->path);
115         free(w);
116 }
117
118 void cgroup_context_free_io_device_limit(CGroupContext *c, CGroupIODeviceLimit *l) {
119         assert(c);
120         assert(l);
121
122         LIST_REMOVE(device_limits, c->io_device_limits, l);
123         free(l->path);
124         free(l);
125 }
126
127 void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODeviceWeight *w) {
128         assert(c);
129         assert(w);
130
131         LIST_REMOVE(device_weights, c->blockio_device_weights, w);
132         free(w->path);
133         free(w);
134 }
135
136 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b) {
137         assert(c);
138         assert(b);
139
140         LIST_REMOVE(device_bandwidths, c->blockio_device_bandwidths, b);
141         free(b->path);
142         free(b);
143 }
144
145 void cgroup_context_done(CGroupContext *c) {
146         assert(c);
147
148         while (c->io_device_weights)
149                 cgroup_context_free_io_device_weight(c, c->io_device_weights);
150
151         while (c->io_device_limits)
152                 cgroup_context_free_io_device_limit(c, c->io_device_limits);
153
154         while (c->blockio_device_weights)
155                 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
156
157         while (c->blockio_device_bandwidths)
158                 cgroup_context_free_blockio_device_bandwidth(c, c->blockio_device_bandwidths);
159
160         while (c->device_allow)
161                 cgroup_context_free_device_allow(c, c->device_allow);
162
163         c->ip_address_allow = ip_address_access_free_all(c->ip_address_allow);
164         c->ip_address_deny = ip_address_access_free_all(c->ip_address_deny);
165 }
166
167 void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
168         CGroupIODeviceLimit *il;
169         CGroupIODeviceWeight *iw;
170         CGroupBlockIODeviceBandwidth *b;
171         CGroupBlockIODeviceWeight *w;
172         CGroupDeviceAllow *a;
173         IPAddressAccessItem *iaai;
174         char u[FORMAT_TIMESPAN_MAX];
175
176         assert(c);
177         assert(f);
178
179         prefix = strempty(prefix);
180
181         fprintf(f,
182                 "%sCPUAccounting=%s\n"
183                 "%sIOAccounting=%s\n"
184                 "%sBlockIOAccounting=%s\n"
185                 "%sMemoryAccounting=%s\n"
186                 "%sTasksAccounting=%s\n"
187                 "%sIPAccounting=%s\n"
188                 "%sCPUWeight=%" PRIu64 "\n"
189                 "%sStartupCPUWeight=%" PRIu64 "\n"
190                 "%sCPUShares=%" PRIu64 "\n"
191                 "%sStartupCPUShares=%" PRIu64 "\n"
192                 "%sCPUQuotaPerSecSec=%s\n"
193                 "%sIOWeight=%" PRIu64 "\n"
194                 "%sStartupIOWeight=%" PRIu64 "\n"
195                 "%sBlockIOWeight=%" PRIu64 "\n"
196                 "%sStartupBlockIOWeight=%" PRIu64 "\n"
197                 "%sMemoryLow=%" PRIu64 "\n"
198                 "%sMemoryHigh=%" PRIu64 "\n"
199                 "%sMemoryMax=%" PRIu64 "\n"
200                 "%sMemorySwapMax=%" PRIu64 "\n"
201                 "%sMemoryLimit=%" PRIu64 "\n"
202                 "%sTasksMax=%" PRIu64 "\n"
203                 "%sDevicePolicy=%s\n"
204                 "%sDelegate=%s\n",
205                 prefix, yes_no(c->cpu_accounting),
206                 prefix, yes_no(c->io_accounting),
207                 prefix, yes_no(c->blockio_accounting),
208                 prefix, yes_no(c->memory_accounting),
209                 prefix, yes_no(c->tasks_accounting),
210                 prefix, yes_no(c->ip_accounting),
211                 prefix, c->cpu_weight,
212                 prefix, c->startup_cpu_weight,
213                 prefix, c->cpu_shares,
214                 prefix, c->startup_cpu_shares,
215                 prefix, format_timespan(u, sizeof(u), c->cpu_quota_per_sec_usec, 1),
216                 prefix, c->io_weight,
217                 prefix, c->startup_io_weight,
218                 prefix, c->blockio_weight,
219                 prefix, c->startup_blockio_weight,
220                 prefix, c->memory_low,
221                 prefix, c->memory_high,
222                 prefix, c->memory_max,
223                 prefix, c->memory_swap_max,
224                 prefix, c->memory_limit,
225                 prefix, c->tasks_max,
226                 prefix, cgroup_device_policy_to_string(c->device_policy),
227                 prefix, yes_no(c->delegate));
228
229         if (c->delegate) {
230                 _cleanup_free_ char *t = NULL;
231
232                 (void) cg_mask_to_string(c->delegate_controllers, &t);
233
234                 fprintf(f, "%sDelegateControllers=%s\n",
235                         prefix,
236                         strempty(t));
237         }
238
239         LIST_FOREACH(device_allow, a, c->device_allow)
240                 fprintf(f,
241                         "%sDeviceAllow=%s %s%s%s\n",
242                         prefix,
243                         a->path,
244                         a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
245
246         LIST_FOREACH(device_weights, iw, c->io_device_weights)
247                 fprintf(f,
248                         "%sIODeviceWeight=%s %" PRIu64,
249                         prefix,
250                         iw->path,
251                         iw->weight);
252
253         LIST_FOREACH(device_limits, il, c->io_device_limits) {
254                 char buf[FORMAT_BYTES_MAX];
255                 CGroupIOLimitType type;
256
257                 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
258                         if (il->limits[type] != cgroup_io_limit_defaults[type])
259                                 fprintf(f,
260                                         "%s%s=%s %s\n",
261                                         prefix,
262                                         cgroup_io_limit_type_to_string(type),
263                                         il->path,
264                                         format_bytes(buf, sizeof(buf), il->limits[type]));
265         }
266
267         LIST_FOREACH(device_weights, w, c->blockio_device_weights)
268                 fprintf(f,
269                         "%sBlockIODeviceWeight=%s %" PRIu64,
270                         prefix,
271                         w->path,
272                         w->weight);
273
274         LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
275                 char buf[FORMAT_BYTES_MAX];
276
277                 if (b->rbps != CGROUP_LIMIT_MAX)
278                         fprintf(f,
279                                 "%sBlockIOReadBandwidth=%s %s\n",
280                                 prefix,
281                                 b->path,
282                                 format_bytes(buf, sizeof(buf), b->rbps));
283                 if (b->wbps != CGROUP_LIMIT_MAX)
284                         fprintf(f,
285                                 "%sBlockIOWriteBandwidth=%s %s\n",
286                                 prefix,
287                                 b->path,
288                                 format_bytes(buf, sizeof(buf), b->wbps));
289         }
290
291         LIST_FOREACH(items, iaai, c->ip_address_allow) {
292                 _cleanup_free_ char *k = NULL;
293
294                 (void) in_addr_to_string(iaai->family, &iaai->address, &k);
295                 fprintf(f, "%sIPAddressAllow=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
296         }
297
298         LIST_FOREACH(items, iaai, c->ip_address_deny) {
299                 _cleanup_free_ char *k = NULL;
300
301                 (void) in_addr_to_string(iaai->family, &iaai->address, &k);
302                 fprintf(f, "%sIPAddressDeny=%s/%u\n", prefix, strnull(k), iaai->prefixlen);
303         }
304 }
305
306 static int lookup_block_device(const char *p, dev_t *dev) {
307         struct stat st;
308         int r;
309
310         assert(p);
311         assert(dev);
312
313         r = stat(p, &st);
314         if (r < 0)
315                 return log_warning_errno(errno, "Couldn't stat device %s: %m", p);
316
317         if (S_ISBLK(st.st_mode))
318                 *dev = st.st_rdev;
319         else if (major(st.st_dev) != 0) {
320                 /* If this is not a device node then find the block
321                  * device this file is stored on */
322                 *dev = st.st_dev;
323
324                 /* If this is a partition, try to get the originating
325                  * block device */
326                 (void) block_get_whole_disk(*dev, dev);
327         } else {
328                 log_warning("%s is not a block device and file system block device cannot be determined or is not local.", p);
329                 return -ENODEV;
330         }
331
332         return 0;
333 }
334
335 static int whitelist_device(const char *path, const char *node, const char *acc) {
336         char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
337         struct stat st;
338         bool ignore_notfound;
339         int r;
340
341         assert(path);
342         assert(acc);
343
344         if (node[0] == '-') {
345                 /* Non-existent paths starting with "-" must be silently ignored */
346                 node++;
347                 ignore_notfound = true;
348         } else
349                 ignore_notfound = false;
350
351         if (stat(node, &st) < 0) {
352                 if (errno == ENOENT && ignore_notfound)
353                         return 0;
354
355                 return log_warning_errno(errno, "Couldn't stat device %s: %m", node);
356         }
357
358         if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode)) {
359                 log_warning("%s is not a device.", node);
360                 return -ENODEV;
361         }
362
363         sprintf(buf,
364                 "%c %u:%u %s",
365                 S_ISCHR(st.st_mode) ? 'c' : 'b',
366                 major(st.st_rdev), minor(st.st_rdev),
367                 acc);
368
369         r = cg_set_attribute("devices", path, "devices.allow", buf);
370         if (r < 0)
371                 log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
372                                "Failed to set devices.allow on %s: %m", path);
373
374         return r;
375 }
376
377 static int whitelist_major(const char *path, const char *name, char type, const char *acc) {
378         _cleanup_fclose_ FILE *f = NULL;
379         char line[LINE_MAX];
380         bool good = false;
381         int r;
382
383         assert(path);
384         assert(acc);
385         assert(IN_SET(type, 'b', 'c'));
386
387         f = fopen("/proc/devices", "re");
388         if (!f)
389                 return log_warning_errno(errno, "Cannot open /proc/devices to resolve %s (%c): %m", name, type);
390
391         FOREACH_LINE(line, f, goto fail) {
392                 char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w;
393                 unsigned maj;
394
395                 truncate_nl(line);
396
397                 if (type == 'c' && streq(line, "Character devices:")) {
398                         good = true;
399                         continue;
400                 }
401
402                 if (type == 'b' && streq(line, "Block devices:")) {
403                         good = true;
404                         continue;
405                 }
406
407                 if (isempty(line)) {
408                         good = false;
409                         continue;
410                 }
411
412                 if (!good)
413                         continue;
414
415                 p = strstrip(line);
416
417                 w = strpbrk(p, WHITESPACE);
418                 if (!w)
419                         continue;
420                 *w = 0;
421
422                 r = safe_atou(p, &maj);
423                 if (r < 0)
424                         continue;
425                 if (maj <= 0)
426                         continue;
427
428                 w++;
429                 w += strspn(w, WHITESPACE);
430
431                 if (fnmatch(name, w, 0) != 0)
432                         continue;
433
434                 sprintf(buf,
435                         "%c %u:* %s",
436                         type,
437                         maj,
438                         acc);
439
440                 r = cg_set_attribute("devices", path, "devices.allow", buf);
441                 if (r < 0)
442                         log_full_errno(IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
443                                        "Failed to set devices.allow on %s: %m", path);
444         }
445
446         return 0;
447
448 fail:
449         return log_warning_errno(errno, "Failed to read /proc/devices: %m");
450 }
451
452 static bool cgroup_context_has_cpu_weight(CGroupContext *c) {
453         return c->cpu_weight != CGROUP_WEIGHT_INVALID ||
454                 c->startup_cpu_weight != CGROUP_WEIGHT_INVALID;
455 }
456
457 static bool cgroup_context_has_cpu_shares(CGroupContext *c) {
458         return c->cpu_shares != CGROUP_CPU_SHARES_INVALID ||
459                 c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID;
460 }
461
462 static uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state) {
463         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
464             c->startup_cpu_weight != CGROUP_WEIGHT_INVALID)
465                 return c->startup_cpu_weight;
466         else if (c->cpu_weight != CGROUP_WEIGHT_INVALID)
467                 return c->cpu_weight;
468         else
469                 return CGROUP_WEIGHT_DEFAULT;
470 }
471
472 static uint64_t cgroup_context_cpu_shares(CGroupContext *c, ManagerState state) {
473         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
474             c->startup_cpu_shares != CGROUP_CPU_SHARES_INVALID)
475                 return c->startup_cpu_shares;
476         else if (c->cpu_shares != CGROUP_CPU_SHARES_INVALID)
477                 return c->cpu_shares;
478         else
479                 return CGROUP_CPU_SHARES_DEFAULT;
480 }
481
482 static void cgroup_apply_unified_cpu_config(Unit *u, uint64_t weight, uint64_t quota) {
483         char buf[MAX(DECIMAL_STR_MAX(uint64_t) + 1, (DECIMAL_STR_MAX(usec_t) + 1) * 2)];
484         int r;
485
486         xsprintf(buf, "%" PRIu64 "\n", weight);
487         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.weight", buf);
488         if (r < 0)
489                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
490                               "Failed to set cpu.weight: %m");
491
492         if (quota != USEC_INFINITY)
493                 xsprintf(buf, USEC_FMT " " USEC_FMT "\n",
494                          quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC, CGROUP_CPU_QUOTA_PERIOD_USEC);
495         else
496                 xsprintf(buf, "max " USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
497
498         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.max", buf);
499
500         if (r < 0)
501                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
502                               "Failed to set cpu.max: %m");
503 }
504
505 static void cgroup_apply_legacy_cpu_config(Unit *u, uint64_t shares, uint64_t quota) {
506         char buf[MAX(DECIMAL_STR_MAX(uint64_t), DECIMAL_STR_MAX(usec_t)) + 1];
507         int r;
508
509         xsprintf(buf, "%" PRIu64 "\n", shares);
510         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.shares", buf);
511         if (r < 0)
512                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
513                               "Failed to set cpu.shares: %m");
514
515         xsprintf(buf, USEC_FMT "\n", CGROUP_CPU_QUOTA_PERIOD_USEC);
516         r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_period_us", buf);
517         if (r < 0)
518                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
519                               "Failed to set cpu.cfs_period_us: %m");
520
521         if (quota != USEC_INFINITY) {
522                 xsprintf(buf, USEC_FMT "\n", quota * CGROUP_CPU_QUOTA_PERIOD_USEC / USEC_PER_SEC);
523                 r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", buf);
524         } else
525                 r = cg_set_attribute("cpu", u->cgroup_path, "cpu.cfs_quota_us", "-1");
526         if (r < 0)
527                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
528                               "Failed to set cpu.cfs_quota_us: %m");
529 }
530
531 static uint64_t cgroup_cpu_shares_to_weight(uint64_t shares) {
532         return CLAMP(shares * CGROUP_WEIGHT_DEFAULT / CGROUP_CPU_SHARES_DEFAULT,
533                      CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX);
534 }
535
536 static uint64_t cgroup_cpu_weight_to_shares(uint64_t weight) {
537         return CLAMP(weight * CGROUP_CPU_SHARES_DEFAULT / CGROUP_WEIGHT_DEFAULT,
538                      CGROUP_CPU_SHARES_MIN, CGROUP_CPU_SHARES_MAX);
539 }
540
541 static bool cgroup_context_has_io_config(CGroupContext *c) {
542         return c->io_accounting ||
543                 c->io_weight != CGROUP_WEIGHT_INVALID ||
544                 c->startup_io_weight != CGROUP_WEIGHT_INVALID ||
545                 c->io_device_weights ||
546                 c->io_device_limits;
547 }
548
549 static bool cgroup_context_has_blockio_config(CGroupContext *c) {
550         return c->blockio_accounting ||
551                 c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
552                 c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID ||
553                 c->blockio_device_weights ||
554                 c->blockio_device_bandwidths;
555 }
556
557 static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) {
558         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
559             c->startup_io_weight != CGROUP_WEIGHT_INVALID)
560                 return c->startup_io_weight;
561         else if (c->io_weight != CGROUP_WEIGHT_INVALID)
562                 return c->io_weight;
563         else
564                 return CGROUP_WEIGHT_DEFAULT;
565 }
566
567 static uint64_t cgroup_context_blkio_weight(CGroupContext *c, ManagerState state) {
568         if (IN_SET(state, MANAGER_STARTING, MANAGER_INITIALIZING) &&
569             c->startup_blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
570                 return c->startup_blockio_weight;
571         else if (c->blockio_weight != CGROUP_BLKIO_WEIGHT_INVALID)
572                 return c->blockio_weight;
573         else
574                 return CGROUP_BLKIO_WEIGHT_DEFAULT;
575 }
576
577 static uint64_t cgroup_weight_blkio_to_io(uint64_t blkio_weight) {
578         return CLAMP(blkio_weight * CGROUP_WEIGHT_DEFAULT / CGROUP_BLKIO_WEIGHT_DEFAULT,
579                      CGROUP_WEIGHT_MIN, CGROUP_WEIGHT_MAX);
580 }
581
582 static uint64_t cgroup_weight_io_to_blkio(uint64_t io_weight) {
583         return CLAMP(io_weight * CGROUP_BLKIO_WEIGHT_DEFAULT / CGROUP_WEIGHT_DEFAULT,
584                      CGROUP_BLKIO_WEIGHT_MIN, CGROUP_BLKIO_WEIGHT_MAX);
585 }
586
587 static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_t io_weight) {
588         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
589         dev_t dev;
590         int r;
591
592         r = lookup_block_device(dev_path, &dev);
593         if (r < 0)
594                 return;
595
596         xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), io_weight);
597         r = cg_set_attribute("io", u->cgroup_path, "io.weight", buf);
598         if (r < 0)
599                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
600                               "Failed to set io.weight: %m");
601 }
602
603 static void cgroup_apply_blkio_device_weight(Unit *u, const char *dev_path, uint64_t blkio_weight) {
604         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
605         dev_t dev;
606         int r;
607
608         r = lookup_block_device(dev_path, &dev);
609         if (r < 0)
610                 return;
611
612         xsprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), blkio_weight);
613         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.weight_device", buf);
614         if (r < 0)
615                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
616                               "Failed to set blkio.weight_device: %m");
617 }
618
619 static unsigned cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
620         char limit_bufs[_CGROUP_IO_LIMIT_TYPE_MAX][DECIMAL_STR_MAX(uint64_t)];
621         char buf[DECIMAL_STR_MAX(dev_t)*2+2+(6+DECIMAL_STR_MAX(uint64_t)+1)*4];
622         CGroupIOLimitType type;
623         dev_t dev;
624         unsigned n = 0;
625         int r;
626
627         r = lookup_block_device(dev_path, &dev);
628         if (r < 0)
629                 return 0;
630
631         for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++) {
632                 if (limits[type] != cgroup_io_limit_defaults[type]) {
633                         xsprintf(limit_bufs[type], "%" PRIu64, limits[type]);
634                         n++;
635                 } else {
636                         xsprintf(limit_bufs[type], "%s", limits[type] == CGROUP_LIMIT_MAX ? "max" : "0");
637                 }
638         }
639
640         xsprintf(buf, "%u:%u rbps=%s wbps=%s riops=%s wiops=%s\n", major(dev), minor(dev),
641                  limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX],
642                  limit_bufs[CGROUP_IO_RIOPS_MAX], limit_bufs[CGROUP_IO_WIOPS_MAX]);
643         r = cg_set_attribute("io", u->cgroup_path, "io.max", buf);
644         if (r < 0)
645                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
646                               "Failed to set io.max: %m");
647         return n;
648 }
649
650 static unsigned cgroup_apply_blkio_device_limit(Unit *u, const char *dev_path, uint64_t rbps, uint64_t wbps) {
651         char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+1];
652         dev_t dev;
653         unsigned n = 0;
654         int r;
655
656         r = lookup_block_device(dev_path, &dev);
657         if (r < 0)
658                 return 0;
659
660         if (rbps != CGROUP_LIMIT_MAX)
661                 n++;
662         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), rbps);
663         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.read_bps_device", buf);
664         if (r < 0)
665                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
666                               "Failed to set blkio.throttle.read_bps_device: %m");
667
668         if (wbps != CGROUP_LIMIT_MAX)
669                 n++;
670         sprintf(buf, "%u:%u %" PRIu64 "\n", major(dev), minor(dev), wbps);
671         r = cg_set_attribute("blkio", u->cgroup_path, "blkio.throttle.write_bps_device", buf);
672         if (r < 0)
673                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
674                               "Failed to set blkio.throttle.write_bps_device: %m");
675
676         return n;
677 }
678
679 static bool cgroup_context_has_unified_memory_config(CGroupContext *c) {
680         return c->memory_low > 0 || c->memory_high != CGROUP_LIMIT_MAX || c->memory_max != CGROUP_LIMIT_MAX || c->memory_swap_max != CGROUP_LIMIT_MAX;
681 }
682
683 static void cgroup_apply_unified_memory_limit(Unit *u, const char *file, uint64_t v) {
684         char buf[DECIMAL_STR_MAX(uint64_t) + 1] = "max";
685         int r;
686
687         if (v != CGROUP_LIMIT_MAX)
688                 xsprintf(buf, "%" PRIu64 "\n", v);
689
690         r = cg_set_attribute("memory", u->cgroup_path, file, buf);
691         if (r < 0)
692                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
693                               "Failed to set %s: %m", file);
694 }
695
696 static void cgroup_apply_firewall(Unit *u) {
697         assert(u);
698
699         /* Best-effort: let's apply IP firewalling and/or accounting if that's enabled */
700
701         if (bpf_firewall_compile(u) < 0)
702                 return;
703
704         (void) bpf_firewall_install(u);
705 }
706
707 static void cgroup_context_apply(
708                 Unit *u,
709                 CGroupMask apply_mask,
710                 bool apply_bpf,
711                 ManagerState state) {
712
713         const char *path;
714         CGroupContext *c;
715         bool is_root;
716         int r;
717
718         assert(u);
719
720         /* Nothing to do? Exit early! */
721         if (apply_mask == 0 && !apply_bpf)
722                 return;
723
724         /* Some cgroup attributes are not supported on the root cgroup, hence silently ignore */
725         is_root = unit_has_root_cgroup(u);
726
727         assert_se(c = unit_get_cgroup_context(u));
728         assert_se(path = u->cgroup_path);
729
730         if (is_root) /* Make sure we don't try to display messages with an empty path. */
731                 path = "/";
732
733         /* We generally ignore errors caused by read-only mounted
734          * cgroup trees (assuming we are running in a container then),
735          * and missing cgroups, i.e. EROFS and ENOENT. */
736
737         if ((apply_mask & CGROUP_MASK_CPU) && !is_root) {
738                 bool has_weight, has_shares;
739
740                 has_weight = cgroup_context_has_cpu_weight(c);
741                 has_shares = cgroup_context_has_cpu_shares(c);
742
743                 if (cg_all_unified() > 0) {
744                         uint64_t weight;
745
746                         if (has_weight)
747                                 weight = cgroup_context_cpu_weight(c, state);
748                         else if (has_shares) {
749                                 uint64_t shares = cgroup_context_cpu_shares(c, state);
750
751                                 weight = cgroup_cpu_shares_to_weight(shares);
752
753                                 log_cgroup_compat(u, "Applying [Startup]CpuShares %" PRIu64 " as [Startup]CpuWeight %" PRIu64 " on %s",
754                                                   shares, weight, path);
755                         } else
756                                 weight = CGROUP_WEIGHT_DEFAULT;
757
758                         cgroup_apply_unified_cpu_config(u, weight, c->cpu_quota_per_sec_usec);
759                 } else {
760                         uint64_t shares;
761
762                         if (has_weight) {
763                                 uint64_t weight = cgroup_context_cpu_weight(c, state);
764
765                                 shares = cgroup_cpu_weight_to_shares(weight);
766
767                                 log_cgroup_compat(u, "Applying [Startup]CpuWeight %" PRIu64 " as [Startup]CpuShares %" PRIu64 " on %s",
768                                                   weight, shares, path);
769                         } else if (has_shares)
770                                 shares = cgroup_context_cpu_shares(c, state);
771                         else
772                                 shares = CGROUP_CPU_SHARES_DEFAULT;
773
774                         cgroup_apply_legacy_cpu_config(u, shares, c->cpu_quota_per_sec_usec);
775                 }
776         }
777
778         if (apply_mask & CGROUP_MASK_IO) {
779                 bool has_io = cgroup_context_has_io_config(c);
780                 bool has_blockio = cgroup_context_has_blockio_config(c);
781
782                 if (!is_root) {
783                         char buf[8+DECIMAL_STR_MAX(uint64_t)+1];
784                         uint64_t weight;
785
786                         if (has_io)
787                                 weight = cgroup_context_io_weight(c, state);
788                         else if (has_blockio) {
789                                 uint64_t blkio_weight = cgroup_context_blkio_weight(c, state);
790
791                                 weight = cgroup_weight_blkio_to_io(blkio_weight);
792
793                                 log_cgroup_compat(u, "Applying [Startup]BlockIOWeight %" PRIu64 " as [Startup]IOWeight %" PRIu64,
794                                                   blkio_weight, weight);
795                         } else
796                                 weight = CGROUP_WEIGHT_DEFAULT;
797
798                         xsprintf(buf, "default %" PRIu64 "\n", weight);
799                         r = cg_set_attribute("io", path, "io.weight", buf);
800                         if (r < 0)
801                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
802                                               "Failed to set io.weight: %m");
803
804                         if (has_io) {
805                                 CGroupIODeviceWeight *w;
806
807                                 /* FIXME: no way to reset this list */
808                                 LIST_FOREACH(device_weights, w, c->io_device_weights)
809                                         cgroup_apply_io_device_weight(u, w->path, w->weight);
810                         } else if (has_blockio) {
811                                 CGroupBlockIODeviceWeight *w;
812
813                                 /* FIXME: no way to reset this list */
814                                 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
815                                         weight = cgroup_weight_blkio_to_io(w->weight);
816
817                                         log_cgroup_compat(u, "Applying BlockIODeviceWeight %" PRIu64 " as IODeviceWeight %" PRIu64 " for %s",
818                                                           w->weight, weight, w->path);
819
820                                         cgroup_apply_io_device_weight(u, w->path, weight);
821                                 }
822                         }
823                 }
824
825                 /* Apply limits and free ones without config. */
826                 if (has_io) {
827                         CGroupIODeviceLimit *l, *next;
828
829                         LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
830                                 if (!cgroup_apply_io_device_limit(u, l->path, l->limits))
831                                         cgroup_context_free_io_device_limit(c, l);
832                         }
833                 } else if (has_blockio) {
834                         CGroupBlockIODeviceBandwidth *b, *next;
835
836                         LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths) {
837                                 uint64_t limits[_CGROUP_IO_LIMIT_TYPE_MAX];
838                                 CGroupIOLimitType type;
839
840                                 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
841                                         limits[type] = cgroup_io_limit_defaults[type];
842
843                                 limits[CGROUP_IO_RBPS_MAX] = b->rbps;
844                                 limits[CGROUP_IO_WBPS_MAX] = b->wbps;
845
846                                 log_cgroup_compat(u, "Applying BlockIO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as IO{Read|Write}BandwidthMax for %s",
847                                                   b->rbps, b->wbps, b->path);
848
849                                 if (!cgroup_apply_io_device_limit(u, b->path, limits))
850                                         cgroup_context_free_blockio_device_bandwidth(c, b);
851                         }
852                 }
853         }
854
855         if (apply_mask & CGROUP_MASK_BLKIO) {
856                 bool has_io = cgroup_context_has_io_config(c);
857                 bool has_blockio = cgroup_context_has_blockio_config(c);
858
859                 if (!is_root) {
860                         char buf[DECIMAL_STR_MAX(uint64_t)+1];
861                         uint64_t weight;
862
863                         if (has_io) {
864                                 uint64_t io_weight = cgroup_context_io_weight(c, state);
865
866                                 weight = cgroup_weight_io_to_blkio(cgroup_context_io_weight(c, state));
867
868                                 log_cgroup_compat(u, "Applying [Startup]IOWeight %" PRIu64 " as [Startup]BlockIOWeight %" PRIu64,
869                                                   io_weight, weight);
870                         } else if (has_blockio)
871                                 weight = cgroup_context_blkio_weight(c, state);
872                         else
873                                 weight = CGROUP_BLKIO_WEIGHT_DEFAULT;
874
875                         xsprintf(buf, "%" PRIu64 "\n", weight);
876                         r = cg_set_attribute("blkio", path, "blkio.weight", buf);
877                         if (r < 0)
878                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
879                                               "Failed to set blkio.weight: %m");
880
881                         if (has_io) {
882                                 CGroupIODeviceWeight *w;
883
884                                 /* FIXME: no way to reset this list */
885                                 LIST_FOREACH(device_weights, w, c->io_device_weights) {
886                                         weight = cgroup_weight_io_to_blkio(w->weight);
887
888                                         log_cgroup_compat(u, "Applying IODeviceWeight %" PRIu64 " as BlockIODeviceWeight %" PRIu64 " for %s",
889                                                           w->weight, weight, w->path);
890
891                                         cgroup_apply_blkio_device_weight(u, w->path, weight);
892                                 }
893                         } else if (has_blockio) {
894                                 CGroupBlockIODeviceWeight *w;
895
896                                 /* FIXME: no way to reset this list */
897                                 LIST_FOREACH(device_weights, w, c->blockio_device_weights)
898                                         cgroup_apply_blkio_device_weight(u, w->path, w->weight);
899                         }
900                 }
901
902                 /* Apply limits and free ones without config. */
903                 if (has_io) {
904                         CGroupIODeviceLimit *l, *next;
905
906                         LIST_FOREACH_SAFE(device_limits, l, next, c->io_device_limits) {
907                                 log_cgroup_compat(u, "Applying IO{Read|Write}Bandwidth %" PRIu64 " %" PRIu64 " as BlockIO{Read|Write}BandwidthMax for %s",
908                                                   l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX], l->path);
909
910                                 if (!cgroup_apply_blkio_device_limit(u, l->path, l->limits[CGROUP_IO_RBPS_MAX], l->limits[CGROUP_IO_WBPS_MAX]))
911                                         cgroup_context_free_io_device_limit(c, l);
912                         }
913                 } else if (has_blockio) {
914                         CGroupBlockIODeviceBandwidth *b, *next;
915
916                         LIST_FOREACH_SAFE(device_bandwidths, b, next, c->blockio_device_bandwidths)
917                                 if (!cgroup_apply_blkio_device_limit(u, b->path, b->rbps, b->wbps))
918                                         cgroup_context_free_blockio_device_bandwidth(c, b);
919                 }
920         }
921
922         if ((apply_mask & CGROUP_MASK_MEMORY) && !is_root) {
923                 if (cg_all_unified() > 0) {
924                         uint64_t max, swap_max = CGROUP_LIMIT_MAX;
925
926                         if (cgroup_context_has_unified_memory_config(c)) {
927                                 max = c->memory_max;
928                                 swap_max = c->memory_swap_max;
929                         } else {
930                                 max = c->memory_limit;
931
932                                 if (max != CGROUP_LIMIT_MAX)
933                                         log_cgroup_compat(u, "Applying MemoryLimit %" PRIu64 " as MemoryMax", max);
934                         }
935
936                         cgroup_apply_unified_memory_limit(u, "memory.low", c->memory_low);
937                         cgroup_apply_unified_memory_limit(u, "memory.high", c->memory_high);
938                         cgroup_apply_unified_memory_limit(u, "memory.max", max);
939                         cgroup_apply_unified_memory_limit(u, "memory.swap.max", swap_max);
940                 } else {
941                         char buf[DECIMAL_STR_MAX(uint64_t) + 1];
942                         uint64_t val;
943
944                         if (cgroup_context_has_unified_memory_config(c)) {
945                                 val = c->memory_max;
946                                 log_cgroup_compat(u, "Applying MemoryMax %" PRIi64 " as MemoryLimit", val);
947                         } else
948                                 val = c->memory_limit;
949
950                         if (val == CGROUP_LIMIT_MAX)
951                                 strncpy(buf, "-1\n", sizeof(buf));
952                         else
953                                 xsprintf(buf, "%" PRIu64 "\n", val);
954
955                         r = cg_set_attribute("memory", path, "memory.limit_in_bytes", buf);
956                         if (r < 0)
957                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
958                                               "Failed to set memory.limit_in_bytes: %m");
959                 }
960         }
961
962         if ((apply_mask & CGROUP_MASK_DEVICES) && !is_root) {
963                 CGroupDeviceAllow *a;
964
965                 /* Changing the devices list of a populated cgroup
966                  * might result in EINVAL, hence ignore EINVAL
967                  * here. */
968
969                 if (c->device_allow || c->device_policy != CGROUP_AUTO)
970                         r = cg_set_attribute("devices", path, "devices.deny", "a");
971                 else
972                         r = cg_set_attribute("devices", path, "devices.allow", "a");
973                 if (r < 0)
974                         log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EINVAL, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
975                                       "Failed to reset devices.list: %m");
976
977                 if (c->device_policy == CGROUP_CLOSED ||
978                     (c->device_policy == CGROUP_AUTO && c->device_allow)) {
979                         static const char auto_devices[] =
980                                 "/dev/null\0" "rwm\0"
981                                 "/dev/zero\0" "rwm\0"
982                                 "/dev/full\0" "rwm\0"
983                                 "/dev/random\0" "rwm\0"
984                                 "/dev/urandom\0" "rwm\0"
985                                 "/dev/tty\0" "rwm\0"
986                                 "/dev/ptmx\0" "rwm\0"
987                                 /* Allow /run/systemd/inaccessible/{chr,blk} devices for mapping InaccessiblePaths */
988                                 "-/run/systemd/inaccessible/chr\0" "rwm\0"
989                                 "-/run/systemd/inaccessible/blk\0" "rwm\0";
990
991                         const char *x, *y;
992
993                         NULSTR_FOREACH_PAIR(x, y, auto_devices)
994                                 whitelist_device(path, x, y);
995
996                         /* PTS (/dev/pts) devices may not be duplicated, but accessed */
997                         whitelist_major(path, "pts", 'c', "rw");
998                 }
999
1000                 LIST_FOREACH(device_allow, a, c->device_allow) {
1001                         char acc[4], *val;
1002                         unsigned k = 0;
1003
1004                         if (a->r)
1005                                 acc[k++] = 'r';
1006                         if (a->w)
1007                                 acc[k++] = 'w';
1008                         if (a->m)
1009                                 acc[k++] = 'm';
1010
1011                         if (k == 0)
1012                                 continue;
1013
1014                         acc[k++] = 0;
1015
1016                         if (path_startswith(a->path, "/dev/"))
1017                                 whitelist_device(path, a->path, acc);
1018                         else if ((val = startswith(a->path, "block-")))
1019                                 whitelist_major(path, val, 'b', acc);
1020                         else if ((val = startswith(a->path, "char-")))
1021                                 whitelist_major(path, val, 'c', acc);
1022                         else
1023                                 log_unit_debug(u, "Ignoring device %s while writing cgroup attribute.", a->path);
1024                 }
1025         }
1026
1027         if (apply_mask & CGROUP_MASK_PIDS) {
1028
1029                 if (is_root) {
1030                         /* So, the "pids" controller does not expose anything on the root cgroup, in order not to
1031                          * replicate knobs exposed elsewhere needlessly. We abstract this away here however, and when
1032                          * the knobs of the root cgroup are modified propagate this to the relevant sysctls. There's a
1033                          * non-obvious asymmetry however: unlike the cgroup properties we don't really want to take
1034                          * exclusive ownership of the sysctls, but we still want to honour things if the user sets
1035                          * limits. Hence we employ sort of a one-way strategy: when the user sets a bounded limit
1036                          * through us it counts. When the user afterwards unsets it again (i.e. sets it to unbounded)
1037                          * it also counts. But if the user never set a limit through us (i.e. we are the default of
1038                          * "unbounded") we leave things unmodified. For this we manage a global boolean that we turn on
1039                          * the first time we set a limit. Note that this boolean is flushed out on manager reload,
1040                          * which is desirable so that there's an offical way to release control of the sysctl from
1041                          * systemd: set the limit to unbounded and reload. */
1042
1043                         if (c->tasks_max != CGROUP_LIMIT_MAX) {
1044                                 u->manager->sysctl_pid_max_changed = true;
1045                                 r = procfs_tasks_set_limit(c->tasks_max);
1046                         } else if (u->manager->sysctl_pid_max_changed)
1047                                 r = procfs_tasks_set_limit(TASKS_MAX);
1048                         else
1049                                 r = 0;
1050
1051                         if (r < 0)
1052                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
1053                                               "Failed to write to tasks limit sysctls: %m");
1054
1055                 } else {
1056                         if (c->tasks_max != CGROUP_LIMIT_MAX) {
1057                                 char buf[DECIMAL_STR_MAX(uint64_t) + 2];
1058
1059                                 sprintf(buf, "%" PRIu64 "\n", c->tasks_max);
1060                                 r = cg_set_attribute("pids", path, "pids.max", buf);
1061                         } else
1062                                 r = cg_set_attribute("pids", path, "pids.max", "max");
1063                         if (r < 0)
1064                                 log_unit_full(u, IN_SET(r, -ENOENT, -EROFS, -EACCES) ? LOG_DEBUG : LOG_WARNING, r,
1065                                               "Failed to set pids.max: %m");
1066                 }
1067         }
1068
1069         if (apply_bpf)
1070                 cgroup_apply_firewall(u);
1071 }
1072
1073 CGroupMask cgroup_context_get_mask(CGroupContext *c) {
1074         CGroupMask mask = 0;
1075
1076         /* Figure out which controllers we need */
1077
1078         if (c->cpu_accounting ||
1079             cgroup_context_has_cpu_weight(c) ||
1080             cgroup_context_has_cpu_shares(c) ||
1081             c->cpu_quota_per_sec_usec != USEC_INFINITY)
1082                 mask |= CGROUP_MASK_CPUACCT | CGROUP_MASK_CPU;
1083
1084         if (cgroup_context_has_io_config(c) || cgroup_context_has_blockio_config(c))
1085                 mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
1086
1087         if (c->memory_accounting ||
1088             c->memory_limit != CGROUP_LIMIT_MAX ||
1089             cgroup_context_has_unified_memory_config(c))
1090                 mask |= CGROUP_MASK_MEMORY;
1091
1092         if (c->device_allow ||
1093             c->device_policy != CGROUP_AUTO)
1094                 mask |= CGROUP_MASK_DEVICES;
1095
1096         if (c->tasks_accounting ||
1097             c->tasks_max != CGROUP_LIMIT_MAX)
1098                 mask |= CGROUP_MASK_PIDS;
1099
1100         return mask;
1101 }
1102
1103 CGroupMask unit_get_own_mask(Unit *u) {
1104         CGroupContext *c;
1105
1106         /* Returns the mask of controllers the unit needs for itself */
1107
1108         c = unit_get_cgroup_context(u);
1109         if (!c)
1110                 return 0;
1111
1112         return cgroup_context_get_mask(c) | unit_get_delegate_mask(u);
1113 }
1114
1115 CGroupMask unit_get_delegate_mask(Unit *u) {
1116         CGroupContext *c;
1117
1118         /* If delegation is turned on, then turn on selected controllers, unless we are on the legacy hierarchy and the
1119          * process we fork into is known to drop privileges, and hence shouldn't get access to the controllers.
1120          *
1121          * Note that on the unified hierarchy it is safe to delegate controllers to unprivileged services. */
1122
1123         if (!unit_cgroup_delegate(u))
1124                 return 0;
1125
1126         if (cg_all_unified() <= 0) {
1127                 ExecContext *e;
1128
1129                 e = unit_get_exec_context(u);
1130                 if (e && !exec_context_maintains_privileges(e))
1131                         return 0;
1132         }
1133
1134         assert_se(c = unit_get_cgroup_context(u));
1135         return c->delegate_controllers;
1136 }
1137
1138 CGroupMask unit_get_members_mask(Unit *u) {
1139         assert(u);
1140
1141         /* Returns the mask of controllers all of the unit's children require, merged */
1142
1143         if (u->cgroup_members_mask_valid)
1144                 return u->cgroup_members_mask;
1145
1146         u->cgroup_members_mask = 0;
1147
1148         if (u->type == UNIT_SLICE) {
1149                 void *v;
1150                 Unit *member;
1151                 Iterator i;
1152
1153                 HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
1154
1155                         if (member == u)
1156                                 continue;
1157
1158                         if (UNIT_DEREF(member->slice) != u)
1159                                 continue;
1160
1161                         u->cgroup_members_mask |= unit_get_subtree_mask(member); /* note that this calls ourselves again, for the children */
1162                 }
1163         }
1164
1165         u->cgroup_members_mask_valid = true;
1166         return u->cgroup_members_mask;
1167 }
1168
1169 CGroupMask unit_get_siblings_mask(Unit *u) {
1170         assert(u);
1171
1172         /* Returns the mask of controllers all of the unit's siblings
1173          * require, i.e. the members mask of the unit's parent slice
1174          * if there is one. */
1175
1176         if (UNIT_ISSET(u->slice))
1177                 return unit_get_members_mask(UNIT_DEREF(u->slice));
1178
1179         return unit_get_subtree_mask(u); /* we are the top-level slice */
1180 }
1181
1182 CGroupMask unit_get_subtree_mask(Unit *u) {
1183
1184         /* Returns the mask of this subtree, meaning of the group
1185          * itself and its children. */
1186
1187         return unit_get_own_mask(u) | unit_get_members_mask(u);
1188 }
1189
1190 CGroupMask unit_get_target_mask(Unit *u) {
1191         CGroupMask mask;
1192
1193         /* This returns the cgroup mask of all controllers to enable
1194          * for a specific cgroup, i.e. everything it needs itself,
1195          * plus all that its children need, plus all that its siblings
1196          * need. This is primarily useful on the legacy cgroup
1197          * hierarchy, where we need to duplicate each cgroup in each
1198          * hierarchy that shall be enabled for it. */
1199
1200         mask = unit_get_own_mask(u) | unit_get_members_mask(u) | unit_get_siblings_mask(u);
1201         mask &= u->manager->cgroup_supported;
1202
1203         return mask;
1204 }
1205
1206 CGroupMask unit_get_enable_mask(Unit *u) {
1207         CGroupMask mask;
1208
1209         /* This returns the cgroup mask of all controllers to enable
1210          * for the children of a specific cgroup. This is primarily
1211          * useful for the unified cgroup hierarchy, where each cgroup
1212          * controls which controllers are enabled for its children. */
1213
1214         mask = unit_get_members_mask(u);
1215         mask &= u->manager->cgroup_supported;
1216
1217         return mask;
1218 }
1219
1220 bool unit_get_needs_bpf(Unit *u) {
1221         CGroupContext *c;
1222         Unit *p;
1223         assert(u);
1224
1225         c = unit_get_cgroup_context(u);
1226         if (!c)
1227                 return false;
1228
1229         if (c->ip_accounting ||
1230             c->ip_address_allow ||
1231             c->ip_address_deny)
1232                 return true;
1233
1234         /* If any parent slice has an IP access list defined, it applies too */
1235         for (p = UNIT_DEREF(u->slice); p; p = UNIT_DEREF(p->slice)) {
1236                 c = unit_get_cgroup_context(p);
1237                 if (!c)
1238                         return false;
1239
1240                 if (c->ip_address_allow ||
1241                     c->ip_address_deny)
1242                         return true;
1243         }
1244
1245         return false;
1246 }
1247
1248 /* Recurse from a unit up through its containing slices, propagating
1249  * mask bits upward. A unit is also member of itself. */
1250 void unit_update_cgroup_members_masks(Unit *u) {
1251         CGroupMask m;
1252         bool more;
1253
1254         assert(u);
1255
1256         /* Calculate subtree mask */
1257         m = unit_get_subtree_mask(u);
1258
1259         /* See if anything changed from the previous invocation. If
1260          * not, we're done. */
1261         if (u->cgroup_subtree_mask_valid && m == u->cgroup_subtree_mask)
1262                 return;
1263
1264         more =
1265                 u->cgroup_subtree_mask_valid &&
1266                 ((m & ~u->cgroup_subtree_mask) != 0) &&
1267                 ((~m & u->cgroup_subtree_mask) == 0);
1268
1269         u->cgroup_subtree_mask = m;
1270         u->cgroup_subtree_mask_valid = true;
1271
1272         if (UNIT_ISSET(u->slice)) {
1273                 Unit *s = UNIT_DEREF(u->slice);
1274
1275                 if (more)
1276                         /* There's more set now than before. We
1277                          * propagate the new mask to the parent's mask
1278                          * (not caring if it actually was valid or
1279                          * not). */
1280
1281                         s->cgroup_members_mask |= m;
1282
1283                 else
1284                         /* There's less set now than before (or we
1285                          * don't know), we need to recalculate
1286                          * everything, so let's invalidate the
1287                          * parent's members mask */
1288
1289                         s->cgroup_members_mask_valid = false;
1290
1291                 /* And now make sure that this change also hits our
1292                  * grandparents */
1293                 unit_update_cgroup_members_masks(s);
1294         }
1295 }
1296
1297 const char *unit_get_realized_cgroup_path(Unit *u, CGroupMask mask) {
1298
1299         /* Returns the realized cgroup path of the specified unit where all specified controllers are available. */
1300
1301         while (u) {
1302
1303                 if (u->cgroup_path &&
1304                     u->cgroup_realized &&
1305                     (u->cgroup_realized_mask & mask) == mask)
1306                         return u->cgroup_path;
1307
1308                 u = UNIT_DEREF(u->slice);
1309         }
1310
1311         return NULL;
1312 }
1313
1314 static const char *migrate_callback(CGroupMask mask, void *userdata) {
1315         return unit_get_realized_cgroup_path(userdata, mask);
1316 }
1317
1318 char *unit_default_cgroup_path(Unit *u) {
1319         _cleanup_free_ char *escaped = NULL, *slice = NULL;
1320         int r;
1321
1322         assert(u);
1323
1324         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1325                 return strdup(u->manager->cgroup_root);
1326
1327         if (UNIT_ISSET(u->slice) && !unit_has_name(UNIT_DEREF(u->slice), SPECIAL_ROOT_SLICE)) {
1328                 r = cg_slice_to_path(UNIT_DEREF(u->slice)->id, &slice);
1329                 if (r < 0)
1330                         return NULL;
1331         }
1332
1333         escaped = cg_escape(u->id);
1334         if (!escaped)
1335                 return NULL;
1336
1337         if (slice)
1338                 return strjoin(u->manager->cgroup_root, "/", slice, "/",
1339                                escaped);
1340         else
1341                 return strjoin(u->manager->cgroup_root, "/", escaped);
1342 }
1343
1344 int unit_set_cgroup_path(Unit *u, const char *path) {
1345         _cleanup_free_ char *p = NULL;
1346         int r;
1347
1348         assert(u);
1349
1350         if (path) {
1351                 p = strdup(path);
1352                 if (!p)
1353                         return -ENOMEM;
1354         } else
1355                 p = NULL;
1356
1357         if (streq_ptr(u->cgroup_path, p))
1358                 return 0;
1359
1360         if (p) {
1361                 r = hashmap_put(u->manager->cgroup_unit, p, u);
1362                 if (r < 0)
1363                         return r;
1364         }
1365
1366         unit_release_cgroup(u);
1367
1368         u->cgroup_path = p;
1369         p = NULL;
1370
1371         return 1;
1372 }
1373
1374 int unit_watch_cgroup(Unit *u) {
1375         _cleanup_free_ char *events = NULL;
1376         int r;
1377
1378         assert(u);
1379
1380         if (!u->cgroup_path)
1381                 return 0;
1382
1383         if (u->cgroup_inotify_wd >= 0)
1384                 return 0;
1385
1386         /* Only applies to the unified hierarchy */
1387         r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
1388         if (r < 0)
1389                 return log_error_errno(r, "Failed to determine whether the name=systemd hierarchy is unified: %m");
1390         if (r == 0)
1391                 return 0;
1392
1393         /* Don't watch the root slice, it's pointless. */
1394         if (unit_has_name(u, SPECIAL_ROOT_SLICE))
1395                 return 0;
1396
1397         r = hashmap_ensure_allocated(&u->manager->cgroup_inotify_wd_unit, &trivial_hash_ops);
1398         if (r < 0)
1399                 return log_oom();
1400
1401         r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, "cgroup.events", &events);
1402         if (r < 0)
1403                 return log_oom();
1404
1405         u->cgroup_inotify_wd = inotify_add_watch(u->manager->cgroup_inotify_fd, events, IN_MODIFY);
1406         if (u->cgroup_inotify_wd < 0) {
1407
1408                 if (errno == ENOENT) /* If the directory is already
1409                                       * gone we don't need to track
1410                                       * it, so this is not an error */
1411                         return 0;
1412
1413                 return log_unit_error_errno(u, errno, "Failed to add inotify watch descriptor for control group %s: %m", u->cgroup_path);
1414         }
1415
1416         r = hashmap_put(u->manager->cgroup_inotify_wd_unit, INT_TO_PTR(u->cgroup_inotify_wd), u);
1417         if (r < 0)
1418                 return log_unit_error_errno(u, r, "Failed to add inotify watch descriptor to hash map: %m");
1419
1420         return 0;
1421 }
1422
1423 int unit_pick_cgroup_path(Unit *u) {
1424         _cleanup_free_ char *path = NULL;
1425         int r;
1426
1427         assert(u);
1428
1429         if (u->cgroup_path)
1430                 return 0;
1431
1432         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1433                 return -EINVAL;
1434
1435         path = unit_default_cgroup_path(u);
1436         if (!path)
1437                 return log_oom();
1438
1439         r = unit_set_cgroup_path(u, path);
1440         if (r == -EEXIST)
1441                 return log_unit_error_errno(u, r, "Control group %s exists already.", path);
1442         if (r < 0)
1443                 return log_unit_error_errno(u, r, "Failed to set unit's control group path to %s: %m", path);
1444
1445         return 0;
1446 }
1447
1448 static int unit_create_cgroup(
1449                 Unit *u,
1450                 CGroupMask target_mask,
1451                 CGroupMask enable_mask,
1452                 bool needs_bpf) {
1453
1454         CGroupContext *c;
1455         int r;
1456
1457         assert(u);
1458
1459         c = unit_get_cgroup_context(u);
1460         if (!c)
1461                 return 0;
1462
1463         /* Figure out our cgroup path */
1464         r = unit_pick_cgroup_path(u);
1465         if (r < 0)
1466                 return r;
1467
1468         /* First, create our own group */
1469         r = cg_create_everywhere(u->manager->cgroup_supported, target_mask, u->cgroup_path);
1470         if (r < 0)
1471                 return log_unit_error_errno(u, r, "Failed to create cgroup %s: %m", u->cgroup_path);
1472
1473         /* Start watching it */
1474         (void) unit_watch_cgroup(u);
1475
1476         /* Enable all controllers we need */
1477         r = cg_enable_everywhere(u->manager->cgroup_supported, enable_mask, u->cgroup_path);
1478         if (r < 0)
1479                 log_unit_warning_errno(u, r, "Failed to enable controllers on cgroup %s, ignoring: %m", u->cgroup_path);
1480
1481         /* Keep track that this is now realized */
1482         u->cgroup_realized = true;
1483         u->cgroup_realized_mask = target_mask;
1484         u->cgroup_enabled_mask = enable_mask;
1485         u->cgroup_bpf_state = needs_bpf ? UNIT_CGROUP_BPF_ON : UNIT_CGROUP_BPF_OFF;
1486
1487         if (u->type != UNIT_SLICE && !unit_cgroup_delegate(u)) {
1488
1489                 /* Then, possibly move things over, but not if
1490                  * subgroups may contain processes, which is the case
1491                  * for slice and delegation units. */
1492                 r = cg_migrate_everywhere(u->manager->cgroup_supported, u->cgroup_path, u->cgroup_path, migrate_callback, u);
1493                 if (r < 0)
1494                         log_unit_warning_errno(u, r, "Failed to migrate cgroup from to %s, ignoring: %m", u->cgroup_path);
1495         }
1496
1497         return 0;
1498 }
1499
1500 static int unit_attach_pid_to_cgroup_via_bus(Unit *u, pid_t pid, const char *suffix_path) {
1501         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1502         char *pp;
1503         int r;
1504
1505         assert(u);
1506
1507         if (MANAGER_IS_SYSTEM(u->manager))
1508                 return -EINVAL;
1509
1510         if (!u->manager->system_bus)
1511                 return -EIO;
1512
1513         if (!u->cgroup_path)
1514                 return -EINVAL;
1515
1516         /* Determine this unit's cgroup path relative to our cgroup root */
1517         pp = path_startswith(u->cgroup_path, u->manager->cgroup_root);
1518         if (!pp)
1519                 return -EINVAL;
1520
1521         pp = strjoina("/", pp, suffix_path);
1522         path_kill_slashes(pp);
1523
1524         r = sd_bus_call_method(u->manager->system_bus,
1525                                "org.freedesktop.systemd1",
1526                                "/org/freedesktop/systemd1",
1527                                "org.freedesktop.systemd1.Manager",
1528                                "AttachProcessesToUnit",
1529                                &error, NULL,
1530                                "ssau",
1531                                NULL /* empty unit name means client's unit, i.e. us */, pp, 1, (uint32_t) pid);
1532         if (r < 0)
1533                 return log_unit_debug_errno(u, r, "Failed to attach unit process " PID_FMT " via the bus: %s", pid, bus_error_message(&error, r));
1534
1535         return 0;
1536 }
1537
1538 int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) {
1539         CGroupMask delegated_mask;
1540         const char *p;
1541         Iterator i;
1542         void *pidp;
1543         int r, q;
1544
1545         assert(u);
1546
1547         if (!UNIT_HAS_CGROUP_CONTEXT(u))
1548                 return -EINVAL;
1549
1550         if (set_isempty(pids))
1551                 return 0;
1552
1553         r = unit_realize_cgroup(u);
1554         if (r < 0)
1555                 return r;
1556
1557         if (isempty(suffix_path))
1558                 p = u->cgroup_path;
1559         else
1560                 p = strjoina(u->cgroup_path, "/", suffix_path);
1561
1562         delegated_mask = unit_get_delegate_mask(u);
1563
1564         r = 0;
1565         SET_FOREACH(pidp, pids, i) {
1566                 pid_t pid = PTR_TO_PID(pidp);
1567                 CGroupController c;
1568
1569                 /* First, attach the PID to the main cgroup hierarchy */
1570                 q = cg_attach(SYSTEMD_CGROUP_CONTROLLER, p, pid);
1571                 if (q < 0) {
1572                         log_unit_debug_errno(u, q, "Couldn't move process " PID_FMT " to requested cgroup '%s': %m", pid, p);
1573
1574                         if (MANAGER_IS_USER(u->manager) && IN_SET(q, -EPERM, -EACCES)) {
1575                                 int z;
1576
1577                                 /* If we are in a user instance, and we can't move the process ourselves due to
1578                                  * permission problems, let's ask the system instance about it instead. Since it's more
1579                                  * privileged it might be able to move the process across the leaves of a subtree who's
1580                                  * top node is not owned by us. */
1581
1582                                 z = unit_attach_pid_to_cgroup_via_bus(u, pid, suffix_path);
1583                                 if (z < 0)
1584                                         log_unit_debug_errno(u, z, "Couldn't move process " PID_FMT " to requested cgroup '%s' via the system bus either: %m", pid, p);
1585                                 else
1586                                         continue; /* When the bus thing worked via the bus we are fully done for this PID. */
1587                         }
1588
1589                         if (r >= 0)
1590                                 r = q; /* Remember first error */
1591
1592                         continue;
1593                 }
1594
1595                 q = cg_all_unified();
1596                 if (q < 0)
1597                         return q;
1598                 if (q > 0)
1599                         continue;
1600
1601                 /* In the legacy hierarchy, attach the process to the request cgroup if possible, and if not to the
1602                  * innermost realized one */
1603
1604                 for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) {
1605                         CGroupMask bit = CGROUP_CONTROLLER_TO_MASK(c);
1606                         const char *realized;
1607
1608                         if (!(u->manager->cgroup_supported & bit))
1609                                 continue;
1610
1611                         /* If this controller is delegated and realized, honour the caller's request for the cgroup suffix. */
1612                         if (delegated_mask & u->cgroup_realized_mask & bit) {
1613                                 q = cg_attach(cgroup_controller_to_string(c), p, pid);
1614                                 if (q >= 0)
1615                                         continue; /* Success! */
1616
1617                                 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",
1618                                                      pid, p, cgroup_controller_to_string(c));
1619                         }
1620
1621                         /* So this controller is either not delegate or realized, or something else weird happened. In
1622                          * that case let's attach the PID at least to the closest cgroup up the tree that is
1623                          * realized. */
1624                         realized = unit_get_realized_cgroup_path(u, bit);
1625                         if (!realized)
1626                                 continue; /* Not even realized in the root slice? Then let's not bother */
1627
1628                         q = cg_attach(cgroup_controller_to_string(c), realized, pid);
1629                         if (q < 0)
1630                                 log_unit_debug_errno(u, q, "Failed to attach PID " PID_FMT " to realized cgroup %s in controller %s, ignoring: %m",
1631                                                      pid, realized, cgroup_controller_to_string(c));
1632                 }
1633         }
1634
1635         return r;
1636 }
1637
1638 static void cgroup_xattr_apply(Unit *u) {
1639         char ids[SD_ID128_STRING_MAX];
1640         int r;
1641
1642         assert(u);
1643
1644         if (!MANAGER_IS_SYSTEM(u->manager))
1645                 return;
1646
1647         if (sd_id128_is_null(u->invocation_id))
1648                 return;
1649
1650         r = cg_set_xattr(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path,
1651                          "trusted.invocation_id",
1652                          sd_id128_to_string(u->invocation_id, ids), 32,
1653                          0);
1654         if (r < 0)
1655                 log_unit_debug_errno(u, r, "Failed to set invocation ID on control group %s, ignoring: %m", u->cgroup_path);
1656 }
1657
1658 static bool unit_has_mask_realized(
1659                 Unit *u,
1660                 CGroupMask target_mask,
1661                 CGroupMask enable_mask,
1662                 bool needs_bpf) {
1663
1664         assert(u);
1665
1666         return u->cgroup_realized &&
1667                 u->cgroup_realized_mask == target_mask &&
1668                 u->cgroup_enabled_mask == enable_mask &&
1669                 ((needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_ON) ||
1670                  (!needs_bpf && u->cgroup_bpf_state == UNIT_CGROUP_BPF_OFF));
1671 }
1672
1673 static void unit_add_to_cgroup_realize_queue(Unit *u) {
1674         assert(u);
1675
1676         if (u->in_cgroup_realize_queue)
1677                 return;
1678
1679         LIST_PREPEND(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
1680         u->in_cgroup_realize_queue = true;
1681 }
1682
1683 static void unit_remove_from_cgroup_realize_queue(Unit *u) {
1684         assert(u);
1685
1686         if (!u->in_cgroup_realize_queue)
1687                 return;
1688
1689         LIST_REMOVE(cgroup_realize_queue, u->manager->cgroup_realize_queue, u);
1690         u->in_cgroup_realize_queue = false;
1691 }
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 #else
2272         /* Note:
2273                 * This method is in core, and normally called by systemd
2274                 * being init. As elogind is never init, we can not install
2275                 * our agent here. We do so when mounting our cgroup file
2276                 * system, so only if elogind is its own tiny controller.
2277                 * Further, elogind is not meant to run in systemd init scope. */
2278         if (MANAGER_IS_SYSTEM(m))
2279                 // we are our own cgroup controller
2280                 scope_path = strjoina("");
2281         else if (streq(m->cgroup_root, "/elogind"))
2282                 // root already is our cgroup
2283                 scope_path = strjoina(m->cgroup_root);
2284         else
2285                 // we have to create our own group
2286                 scope_path = strjoina(m->cgroup_root, "/elogind");
2287         r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2288 #endif // 0
2289         if (r < 0)
2290                 return log_error_errno(r, "Failed to create %s control group: %m", scope_path);
2291         log_debug_elogind("Created control group \"%s\"", scope_path);
2292
2293 #if 0 /// elogind is not a "sub-controller" like systemd, so migration is not needed.
2294         /* Also, move all other userspace processes remaining in the root cgroup into that scope. */
2295         r = cg_migrate(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, SYSTEMD_CGROUP_CONTROLLER, scope_path, 0);
2296         if (r < 0)
2297                 log_warning_errno(r, "Couldn't move remaining userspace processes, ignoring: %m");
2298 #endif // 0
2299
2300         /* 6. And pin it, so that it cannot be unmounted */
2301         safe_close(m->pin_cgroupfs_fd);
2302         m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK);
2303         if (m->pin_cgroupfs_fd < 0)
2304                 return log_error_errno(errno, "Failed to open pin file: %m");
2305
2306         /* 7. Always enable hierarchical support if it exists... */
2307         if (!all_unified && m->test_run_flags == 0)
2308                 (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
2309
2310         /* 8. Figure out which controllers are supported, and log about it */
2311         r = cg_mask_supported(&m->cgroup_supported);
2312         if (r < 0)
2313                 return log_error_errno(r, "Failed to determine supported controllers: %m");
2314         for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++)
2315                 log_debug("Controller '%s' supported: %s", cgroup_controller_to_string(c), yes_no(m->cgroup_supported & CGROUP_CONTROLLER_TO_MASK(c)));
2316
2317         return 0;
2318 }
2319
2320 void manager_shutdown_cgroup(Manager *m, bool delete) {
2321         assert(m);
2322
2323         /* We can't really delete the group, since we are in it. But
2324          * let's trim it. */
2325         if (delete && m->cgroup_root)
2326                 (void) cg_trim(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_root, false);
2327
2328 #if 0 /// elogind is not init
2329         m->cgroup_empty_event_source = sd_event_source_unref(m->cgroup_empty_event_source);
2330
2331         m->cgroup_inotify_wd_unit = hashmap_free(m->cgroup_inotify_wd_unit);
2332
2333         m->cgroup_inotify_event_source = sd_event_source_unref(m->cgroup_inotify_event_source);
2334         m->cgroup_inotify_fd = safe_close(m->cgroup_inotify_fd);
2335 #endif // 0
2336
2337         m->pin_cgroupfs_fd = safe_close(m->pin_cgroupfs_fd);
2338
2339         m->cgroup_root = mfree(m->cgroup_root);
2340 }
2341
2342 #if 0 /// UNNEEDED by elogind
2343 Unit* manager_get_unit_by_cgroup(Manager *m, const char *cgroup) {
2344         char *p;
2345         Unit *u;
2346
2347         assert(m);
2348         assert(cgroup);
2349
2350         u = hashmap_get(m->cgroup_unit, cgroup);
2351         if (u)
2352                 return u;
2353
2354         p = strdupa(cgroup);
2355         for (;;) {
2356                 char *e;
2357
2358                 e = strrchr(p, '/');
2359                 if (!e || e == p)
2360                         return hashmap_get(m->cgroup_unit, SPECIAL_ROOT_SLICE);
2361
2362                 *e = 0;
2363
2364                 u = hashmap_get(m->cgroup_unit, p);
2365                 if (u)
2366                         return u;
2367         }
2368 }
2369
2370 Unit *manager_get_unit_by_pid_cgroup(Manager *m, pid_t pid) {
2371         _cleanup_free_ char *cgroup = NULL;
2372
2373         assert(m);
2374
2375         if (!pid_is_valid(pid))
2376                 return NULL;
2377
2378         if (cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup) < 0)
2379                 return NULL;
2380
2381         return manager_get_unit_by_cgroup(m, cgroup);
2382 }
2383
2384 Unit *manager_get_unit_by_pid(Manager *m, pid_t pid) {
2385         Unit *u, **array;
2386
2387         assert(m);
2388
2389         /* Note that a process might be owned by multiple units, we return only one here, which is good enough for most
2390          * cases, though not strictly correct. We prefer the one reported by cgroup membership, as that's the most
2391          * relevant one as children of the process will be assigned to that one, too, before all else. */
2392
2393         if (!pid_is_valid(pid))
2394                 return NULL;
2395
2396         if (pid == getpid_cached())
2397                 return hashmap_get(m->units, SPECIAL_INIT_SCOPE);
2398
2399         u = manager_get_unit_by_pid_cgroup(m, pid);
2400         if (u)
2401                 return u;
2402
2403         u = hashmap_get(m->watch_pids, PID_TO_PTR(pid));
2404         if (u)
2405                 return u;
2406
2407         array = hashmap_get(m->watch_pids, PID_TO_PTR(-pid));
2408         if (array)
2409                 return array[0];
2410
2411         return NULL;
2412 }
2413 #endif // 0
2414
2415 #if 0 /// elogind must substitute this with its own variant
2416 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
2417         Unit *u;
2418
2419         assert(m);
2420         assert(cgroup);
2421
2422         /* Called on the legacy hierarchy whenever we get an explicit cgroup notification from the cgroup agent process
2423          * or from the --system instance */
2424
2425         log_debug("Got cgroup empty notification for: %s", cgroup);
2426
2427         u = manager_get_unit_by_cgroup(m, cgroup);
2428         if (!u)
2429                 return 0;
2430
2431         unit_add_to_cgroup_empty_queue(u);
2432         return 1;
2433 }
2434 #else
2435 int manager_notify_cgroup_empty(Manager *m, const char *cgroup) {
2436         Session *s;
2437
2438         assert(m);
2439         assert(cgroup);
2440
2441         log_debug("Got cgroup empty notification for: %s", cgroup);
2442
2443         s = hashmap_get(m->sessions, cgroup);
2444
2445         if (s) {
2446                 session_finalize(s);
2447                 session_free(s);
2448         } else
2449                 log_warning("Session not found: %s", cgroup);
2450
2451         return 0;
2452 }
2453 #endif // 0
2454 #if 0 /// UNNEEDED by elogind
2455 int unit_get_memory_current(Unit *u, uint64_t *ret) {
2456         _cleanup_free_ char *v = NULL;
2457         int r;
2458
2459         assert(u);
2460         assert(ret);
2461
2462         if (!UNIT_CGROUP_BOOL(u, memory_accounting))
2463                 return -ENODATA;
2464
2465         if (!u->cgroup_path)
2466                 return -ENODATA;
2467
2468         if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
2469                 return -ENODATA;
2470
2471         r = cg_all_unified();
2472         if (r < 0)
2473                 return r;
2474         if (r > 0)
2475                 r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v);
2476         else
2477                 r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
2478         if (r == -ENOENT)
2479                 return -ENODATA;
2480         if (r < 0)
2481                 return r;
2482
2483         return safe_atou64(v, ret);
2484 }
2485
2486 int unit_get_tasks_current(Unit *u, uint64_t *ret) {
2487         _cleanup_free_ char *v = NULL;
2488         int r;
2489
2490         assert(u);
2491         assert(ret);
2492
2493         if (!UNIT_CGROUP_BOOL(u, tasks_accounting))
2494                 return -ENODATA;
2495
2496         if (!u->cgroup_path)
2497                 return -ENODATA;
2498
2499         if ((u->cgroup_realized_mask & CGROUP_MASK_PIDS) == 0)
2500                 return -ENODATA;
2501
2502         /* The root cgroup doesn't expose this information, let's get it from /proc instead */
2503         if (unit_has_root_cgroup(u))
2504                 return procfs_tasks_get_current(ret);
2505
2506         r = cg_get_attribute("pids", u->cgroup_path, "pids.current", &v);
2507         if (r == -ENOENT)
2508                 return -ENODATA;
2509         if (r < 0)
2510                 return r;
2511
2512         return safe_atou64(v, ret);
2513 }
2514
2515 static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
2516         _cleanup_free_ char *v = NULL;
2517         uint64_t ns;
2518         int r;
2519
2520         assert(u);
2521         assert(ret);
2522
2523         if (!u->cgroup_path)
2524                 return -ENODATA;
2525
2526         r = cg_all_unified();
2527         if (r < 0)
2528                 return r;
2529         if (r > 0) {
2530                 const char *keys[] = { "usage_usec", NULL };
2531                 _cleanup_free_ char *val = NULL;
2532                 uint64_t us;
2533
2534                 if ((u->cgroup_realized_mask & CGROUP_MASK_CPU) == 0)
2535                         return -ENODATA;
2536
2537                 r = cg_get_keyed_attribute("cpu", u->cgroup_path, "cpu.stat", keys, &val);
2538                 if (r < 0)
2539                         return r;
2540
2541                 r = safe_atou64(val, &us);
2542                 if (r < 0)
2543                         return r;
2544
2545                 ns = us * NSEC_PER_USEC;
2546         } else {
2547                 if ((u->cgroup_realized_mask & CGROUP_MASK_CPUACCT) == 0)
2548                         return -ENODATA;
2549
2550                 r = cg_get_attribute("cpuacct", u->cgroup_path, "cpuacct.usage", &v);
2551                 if (r == -ENOENT)
2552                         return -ENODATA;
2553                 if (r < 0)
2554                         return r;
2555
2556                 r = safe_atou64(v, &ns);
2557                 if (r < 0)
2558                         return r;
2559         }
2560
2561         *ret = ns;
2562         return 0;
2563 }
2564
2565 int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
2566         nsec_t ns;
2567         int r;
2568
2569         assert(u);
2570
2571         /* Retrieve the current CPU usage counter. This will subtract the CPU counter taken when the unit was
2572          * started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply
2573          * call this function with a NULL return value. */
2574
2575         if (!UNIT_CGROUP_BOOL(u, cpu_accounting))
2576                 return -ENODATA;
2577
2578         r = unit_get_cpu_usage_raw(u, &ns);
2579         if (r == -ENODATA && u->cpu_usage_last != NSEC_INFINITY) {
2580                 /* If we can't get the CPU usage anymore (because the cgroup was already removed, for example), use our
2581                  * cached value. */
2582
2583                 if (ret)
2584                         *ret = u->cpu_usage_last;
2585                 return 0;
2586         }
2587         if (r < 0)
2588                 return r;
2589
2590         if (ns > u->cpu_usage_base)
2591                 ns -= u->cpu_usage_base;
2592         else
2593                 ns = 0;
2594
2595         u->cpu_usage_last = ns;
2596         if (ret)
2597                 *ret = ns;
2598
2599         return 0;
2600 }
2601
2602 int unit_get_ip_accounting(
2603                 Unit *u,
2604                 CGroupIPAccountingMetric metric,
2605                 uint64_t *ret) {
2606
2607         uint64_t value;
2608         int fd, r;
2609
2610         assert(u);
2611         assert(metric >= 0);
2612         assert(metric < _CGROUP_IP_ACCOUNTING_METRIC_MAX);
2613         assert(ret);
2614
2615         if (!UNIT_CGROUP_BOOL(u, ip_accounting))
2616                 return -ENODATA;
2617
2618         fd = IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_INGRESS_PACKETS) ?
2619                 u->ip_accounting_ingress_map_fd :
2620                 u->ip_accounting_egress_map_fd;
2621         if (fd < 0)
2622                 return -ENODATA;
2623
2624         if (IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_EGRESS_BYTES))
2625                 r = bpf_firewall_read_accounting(fd, &value, NULL);
2626         else
2627                 r = bpf_firewall_read_accounting(fd, NULL, &value);
2628         if (r < 0)
2629                 return r;
2630
2631         /* Add in additional metrics from a previous runtime. Note that when reexecing/reloading the daemon we compile
2632          * all BPF programs and maps anew, but serialize the old counters. When deserializing we store them in the
2633          * ip_accounting_extra[] field, and add them in here transparently. */
2634
2635         *ret = value + u->ip_accounting_extra[metric];
2636
2637         return r;
2638 }
2639
2640 int unit_reset_cpu_accounting(Unit *u) {
2641         nsec_t ns;
2642         int r;
2643
2644         assert(u);
2645
2646         u->cpu_usage_last = NSEC_INFINITY;
2647
2648         r = unit_get_cpu_usage_raw(u, &ns);
2649         if (r < 0) {
2650                 u->cpu_usage_base = 0;
2651                 return r;
2652         }
2653
2654         u->cpu_usage_base = ns;
2655         return 0;
2656 }
2657
2658 int unit_reset_ip_accounting(Unit *u) {
2659         int r = 0, q = 0;
2660
2661         assert(u);
2662
2663         if (u->ip_accounting_ingress_map_fd >= 0)
2664                 r = bpf_firewall_reset_accounting(u->ip_accounting_ingress_map_fd);
2665
2666         if (u->ip_accounting_egress_map_fd >= 0)
2667                 q = bpf_firewall_reset_accounting(u->ip_accounting_egress_map_fd);
2668
2669         zero(u->ip_accounting_extra);
2670
2671         return r < 0 ? r : q;
2672 }
2673
2674 void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
2675         assert(u);
2676
2677         if (!UNIT_HAS_CGROUP_CONTEXT(u))
2678                 return;
2679
2680         if (m == 0)
2681                 return;
2682
2683         /* always invalidate compat pairs together */
2684         if (m & (CGROUP_MASK_IO | CGROUP_MASK_BLKIO))
2685                 m |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
2686
2687         if (m & (CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT))
2688                 m |= CGROUP_MASK_CPU | CGROUP_MASK_CPUACCT;
2689
2690         if ((u->cgroup_realized_mask & m) == 0) /* NOP? */
2691                 return;
2692
2693         u->cgroup_realized_mask &= ~m;
2694         unit_add_to_cgroup_realize_queue(u);
2695 }
2696
2697 void unit_invalidate_cgroup_bpf(Unit *u) {
2698         assert(u);
2699
2700         if (!UNIT_HAS_CGROUP_CONTEXT(u))
2701                 return;
2702
2703         if (u->cgroup_bpf_state == UNIT_CGROUP_BPF_INVALIDATED) /* NOP? */
2704                 return;
2705
2706         u->cgroup_bpf_state = UNIT_CGROUP_BPF_INVALIDATED;
2707         unit_add_to_cgroup_realize_queue(u);
2708
2709         /* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access
2710          * list of our children includes our own. */
2711         if (u->type == UNIT_SLICE) {
2712                 Unit *member;
2713                 Iterator i;
2714                 void *v;
2715
2716                 HASHMAP_FOREACH_KEY(v, member, u->dependencies[UNIT_BEFORE], i) {
2717                         if (member == u)
2718                                 continue;
2719
2720                         if (UNIT_DEREF(member->slice) != u)
2721                                 continue;
2722
2723                         unit_invalidate_cgroup_bpf(member);
2724                 }
2725         }
2726 }
2727
2728 bool unit_cgroup_delegate(Unit *u) {
2729         CGroupContext *c;
2730
2731         assert(u);
2732
2733         if (!UNIT_VTABLE(u)->can_delegate)
2734                 return false;
2735
2736         c = unit_get_cgroup_context(u);
2737         if (!c)
2738                 return false;
2739
2740         return c->delegate;
2741 }
2742
2743 void manager_invalidate_startup_units(Manager *m) {
2744         Iterator i;
2745         Unit *u;
2746
2747         assert(m);
2748
2749         SET_FOREACH(u, m->startup_units, i)
2750                 unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO);
2751 }
2752
2753 static const char* const cgroup_device_policy_table[_CGROUP_DEVICE_POLICY_MAX] = {
2754         [CGROUP_AUTO] = "auto",
2755         [CGROUP_CLOSED] = "closed",
2756         [CGROUP_STRICT] = "strict",
2757 };
2758
2759 DEFINE_STRING_TABLE_LOOKUP(cgroup_device_policy, CGroupDevicePolicy);
2760 #endif // 0