]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-cgroup.c
Merge pull request #8296 from poettering/resolvconf
[thirdparty/systemd.git] / src / core / dbus-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 <arpa/inet.h>
22 #include <stdio_ext.h>
23
24 #include "af-list.h"
25 #include "alloc-util.h"
26 #include "bpf-firewall.h"
27 #include "bus-util.h"
28 #include "cgroup-util.h"
29 #include "cgroup.h"
30 #include "dbus-cgroup.h"
31 #include "dbus-util.h"
32 #include "fd-util.h"
33 #include "fileio.h"
34 #include "path-util.h"
35
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_cgroup_device_policy, cgroup_device_policy, CGroupDevicePolicy);
37
38 static int property_get_delegate_controllers(
39 sd_bus *bus,
40 const char *path,
41 const char *interface,
42 const char *property,
43 sd_bus_message *reply,
44 void *userdata,
45 sd_bus_error *error) {
46
47 CGroupContext *c = userdata;
48 CGroupController cc;
49 int r;
50
51 assert(bus);
52 assert(reply);
53 assert(c);
54
55 if (!c->delegate)
56 return sd_bus_message_append(reply, "as", 0);
57
58 r = sd_bus_message_open_container(reply, 'a', "s");
59 if (r < 0)
60 return r;
61
62 for (cc = 0; cc < _CGROUP_CONTROLLER_MAX; cc++) {
63 if ((c->delegate_controllers & CGROUP_CONTROLLER_TO_MASK(cc)) == 0)
64 continue;
65
66 r = sd_bus_message_append(reply, "s", cgroup_controller_to_string(cc));
67 if (r < 0)
68 return r;
69 }
70
71 return sd_bus_message_close_container(reply);
72 }
73
74 static int property_get_io_device_weight(
75 sd_bus *bus,
76 const char *path,
77 const char *interface,
78 const char *property,
79 sd_bus_message *reply,
80 void *userdata,
81 sd_bus_error *error) {
82
83 CGroupContext *c = userdata;
84 CGroupIODeviceWeight *w;
85 int r;
86
87 assert(bus);
88 assert(reply);
89 assert(c);
90
91 r = sd_bus_message_open_container(reply, 'a', "(st)");
92 if (r < 0)
93 return r;
94
95 LIST_FOREACH(device_weights, w, c->io_device_weights) {
96 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
97 if (r < 0)
98 return r;
99 }
100
101 return sd_bus_message_close_container(reply);
102 }
103
104 static int property_get_io_device_limits(
105 sd_bus *bus,
106 const char *path,
107 const char *interface,
108 const char *property,
109 sd_bus_message *reply,
110 void *userdata,
111 sd_bus_error *error) {
112
113 CGroupContext *c = userdata;
114 CGroupIODeviceLimit *l;
115 int r;
116
117 assert(bus);
118 assert(reply);
119 assert(c);
120
121 r = sd_bus_message_open_container(reply, 'a', "(st)");
122 if (r < 0)
123 return r;
124
125 LIST_FOREACH(device_limits, l, c->io_device_limits) {
126 CGroupIOLimitType type;
127
128 type = cgroup_io_limit_type_from_string(property);
129 if (type < 0 || l->limits[type] == cgroup_io_limit_defaults[type])
130 continue;
131
132 r = sd_bus_message_append(reply, "(st)", l->path, l->limits[type]);
133 if (r < 0)
134 return r;
135 }
136
137 return sd_bus_message_close_container(reply);
138 }
139
140 static int property_get_blockio_device_weight(
141 sd_bus *bus,
142 const char *path,
143 const char *interface,
144 const char *property,
145 sd_bus_message *reply,
146 void *userdata,
147 sd_bus_error *error) {
148
149 CGroupContext *c = userdata;
150 CGroupBlockIODeviceWeight *w;
151 int r;
152
153 assert(bus);
154 assert(reply);
155 assert(c);
156
157 r = sd_bus_message_open_container(reply, 'a', "(st)");
158 if (r < 0)
159 return r;
160
161 LIST_FOREACH(device_weights, w, c->blockio_device_weights) {
162 r = sd_bus_message_append(reply, "(st)", w->path, w->weight);
163 if (r < 0)
164 return r;
165 }
166
167 return sd_bus_message_close_container(reply);
168 }
169
170 static int property_get_blockio_device_bandwidths(
171 sd_bus *bus,
172 const char *path,
173 const char *interface,
174 const char *property,
175 sd_bus_message *reply,
176 void *userdata,
177 sd_bus_error *error) {
178
179 CGroupContext *c = userdata;
180 CGroupBlockIODeviceBandwidth *b;
181 int r;
182
183 assert(bus);
184 assert(reply);
185 assert(c);
186
187 r = sd_bus_message_open_container(reply, 'a', "(st)");
188 if (r < 0)
189 return r;
190
191 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
192 uint64_t v;
193
194 if (streq(property, "BlockIOReadBandwidth"))
195 v = b->rbps;
196 else
197 v = b->wbps;
198
199 if (v == CGROUP_LIMIT_MAX)
200 continue;
201
202 r = sd_bus_message_append(reply, "(st)", b->path, v);
203 if (r < 0)
204 return r;
205 }
206
207 return sd_bus_message_close_container(reply);
208 }
209
210 static int property_get_device_allow(
211 sd_bus *bus,
212 const char *path,
213 const char *interface,
214 const char *property,
215 sd_bus_message *reply,
216 void *userdata,
217 sd_bus_error *error) {
218
219 CGroupContext *c = userdata;
220 CGroupDeviceAllow *a;
221 int r;
222
223 assert(bus);
224 assert(reply);
225 assert(c);
226
227 r = sd_bus_message_open_container(reply, 'a', "(ss)");
228 if (r < 0)
229 return r;
230
231 LIST_FOREACH(device_allow, a, c->device_allow) {
232 unsigned k = 0;
233 char rwm[4];
234
235 if (a->r)
236 rwm[k++] = 'r';
237 if (a->w)
238 rwm[k++] = 'w';
239 if (a->m)
240 rwm[k++] = 'm';
241
242 rwm[k] = 0;
243
244 r = sd_bus_message_append(reply, "(ss)", a->path, rwm);
245 if (r < 0)
246 return r;
247 }
248
249 return sd_bus_message_close_container(reply);
250 }
251
252 static int property_get_ip_address_access(
253 sd_bus *bus,
254 const char *path,
255 const char *interface,
256 const char *property,
257 sd_bus_message *reply,
258 void *userdata,
259 sd_bus_error *error) {
260
261 IPAddressAccessItem** items = userdata, *i;
262 int r;
263
264 r = sd_bus_message_open_container(reply, 'a', "(iayu)");
265 if (r < 0)
266 return r;
267
268 LIST_FOREACH(items, i, *items) {
269
270 r = sd_bus_message_open_container(reply, 'r', "iayu");
271 if (r < 0)
272 return r;
273
274 r = sd_bus_message_append(reply, "i", i->family);
275 if (r < 0)
276 return r;
277
278 r = sd_bus_message_append_array(reply, 'y', &i->address, FAMILY_ADDRESS_SIZE(i->family));
279 if (r < 0)
280 return r;
281
282 r = sd_bus_message_append(reply, "u", (uint32_t) i->prefixlen);
283 if (r < 0)
284 return r;
285
286 r = sd_bus_message_close_container(reply);
287 if (r < 0)
288 return r;
289 }
290
291 return sd_bus_message_close_container(reply);
292 }
293
294 const sd_bus_vtable bus_cgroup_vtable[] = {
295 SD_BUS_VTABLE_START(0),
296 SD_BUS_PROPERTY("Delegate", "b", bus_property_get_bool, offsetof(CGroupContext, delegate), 0),
297 SD_BUS_PROPERTY("DelegateControllers", "as", property_get_delegate_controllers, 0, 0),
298 SD_BUS_PROPERTY("CPUAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, cpu_accounting), 0),
299 SD_BUS_PROPERTY("CPUWeight", "t", NULL, offsetof(CGroupContext, cpu_weight), 0),
300 SD_BUS_PROPERTY("StartupCPUWeight", "t", NULL, offsetof(CGroupContext, startup_cpu_weight), 0),
301 SD_BUS_PROPERTY("CPUShares", "t", NULL, offsetof(CGroupContext, cpu_shares), 0),
302 SD_BUS_PROPERTY("StartupCPUShares", "t", NULL, offsetof(CGroupContext, startup_cpu_shares), 0),
303 SD_BUS_PROPERTY("CPUQuotaPerSecUSec", "t", bus_property_get_usec, offsetof(CGroupContext, cpu_quota_per_sec_usec), 0),
304 SD_BUS_PROPERTY("IOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, io_accounting), 0),
305 SD_BUS_PROPERTY("IOWeight", "t", NULL, offsetof(CGroupContext, io_weight), 0),
306 SD_BUS_PROPERTY("StartupIOWeight", "t", NULL, offsetof(CGroupContext, startup_io_weight), 0),
307 SD_BUS_PROPERTY("IODeviceWeight", "a(st)", property_get_io_device_weight, 0, 0),
308 SD_BUS_PROPERTY("IOReadBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
309 SD_BUS_PROPERTY("IOWriteBandwidthMax", "a(st)", property_get_io_device_limits, 0, 0),
310 SD_BUS_PROPERTY("IOReadIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
311 SD_BUS_PROPERTY("IOWriteIOPSMax", "a(st)", property_get_io_device_limits, 0, 0),
312 SD_BUS_PROPERTY("BlockIOAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, blockio_accounting), 0),
313 SD_BUS_PROPERTY("BlockIOWeight", "t", NULL, offsetof(CGroupContext, blockio_weight), 0),
314 SD_BUS_PROPERTY("StartupBlockIOWeight", "t", NULL, offsetof(CGroupContext, startup_blockio_weight), 0),
315 SD_BUS_PROPERTY("BlockIODeviceWeight", "a(st)", property_get_blockio_device_weight, 0, 0),
316 SD_BUS_PROPERTY("BlockIOReadBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
317 SD_BUS_PROPERTY("BlockIOWriteBandwidth", "a(st)", property_get_blockio_device_bandwidths, 0, 0),
318 SD_BUS_PROPERTY("MemoryAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, memory_accounting), 0),
319 SD_BUS_PROPERTY("MemoryLow", "t", NULL, offsetof(CGroupContext, memory_low), 0),
320 SD_BUS_PROPERTY("MemoryHigh", "t", NULL, offsetof(CGroupContext, memory_high), 0),
321 SD_BUS_PROPERTY("MemoryMax", "t", NULL, offsetof(CGroupContext, memory_max), 0),
322 SD_BUS_PROPERTY("MemorySwapMax", "t", NULL, offsetof(CGroupContext, memory_swap_max), 0),
323 SD_BUS_PROPERTY("MemoryLimit", "t", NULL, offsetof(CGroupContext, memory_limit), 0),
324 SD_BUS_PROPERTY("DevicePolicy", "s", property_get_cgroup_device_policy, offsetof(CGroupContext, device_policy), 0),
325 SD_BUS_PROPERTY("DeviceAllow", "a(ss)", property_get_device_allow, 0, 0),
326 SD_BUS_PROPERTY("TasksAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, tasks_accounting), 0),
327 SD_BUS_PROPERTY("TasksMax", "t", NULL, offsetof(CGroupContext, tasks_max), 0),
328 SD_BUS_PROPERTY("IPAccounting", "b", bus_property_get_bool, offsetof(CGroupContext, ip_accounting), 0),
329 SD_BUS_PROPERTY("IPAddressAllow", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_allow), 0),
330 SD_BUS_PROPERTY("IPAddressDeny", "a(iayu)", property_get_ip_address_access, offsetof(CGroupContext, ip_address_deny), 0),
331 SD_BUS_VTABLE_END
332 };
333
334 static int bus_cgroup_set_transient_property(
335 Unit *u,
336 CGroupContext *c,
337 const char *name,
338 sd_bus_message *message,
339 UnitWriteFlags flags,
340 sd_bus_error *error) {
341
342 int r;
343
344 assert(u);
345 assert(c);
346 assert(name);
347 assert(message);
348
349 flags |= UNIT_PRIVATE;
350
351 if (streq(name, "Delegate")) {
352 int b;
353
354 if (!UNIT_VTABLE(u)->can_delegate)
355 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
356
357 r = sd_bus_message_read(message, "b", &b);
358 if (r < 0)
359 return r;
360
361 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
362 c->delegate = b;
363 c->delegate_controllers = b ? _CGROUP_MASK_ALL : 0;
364
365 unit_write_settingf(u, flags, name, "Delegate=%s", yes_no(b));
366 }
367
368 return 1;
369
370 } else if (streq(name, "DelegateControllers")) {
371 CGroupMask mask = 0;
372
373 if (!UNIT_VTABLE(u)->can_delegate)
374 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delegation not available for unit type");
375
376 r = sd_bus_message_enter_container(message, 'a', "s");
377 if (r < 0)
378 return r;
379
380 for (;;) {
381 CGroupController cc;
382 const char *t;
383
384 r = sd_bus_message_read(message, "s", &t);
385 if (r < 0)
386 return r;
387 if (r == 0)
388 break;
389
390 cc = cgroup_controller_from_string(t);
391 if (cc < 0)
392 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown cgroup contoller '%s'", t);
393
394 mask |= CGROUP_CONTROLLER_TO_MASK(cc);
395 }
396
397 r = sd_bus_message_exit_container(message);
398 if (r < 0)
399 return r;
400
401 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
402 _cleanup_free_ char *t = NULL;
403
404 r = cg_mask_to_string(mask, &t);
405 if (r < 0)
406 return r;
407
408 c->delegate = true;
409 if (mask == 0)
410 c->delegate_controllers = 0;
411 else
412 c->delegate_controllers |= mask;
413
414 unit_write_settingf(u, flags, name, "Delegate=%s", strempty(t));
415 }
416
417 return 1;
418 }
419
420 return 0;
421 }
422
423 static int bus_cgroup_set_boolean(
424 Unit *u,
425 const char *name,
426 bool *p,
427 CGroupMask mask,
428 sd_bus_message *message,
429 UnitWriteFlags flags,
430 sd_bus_error *error) {
431
432 int b, r;
433
434 assert(p);
435
436 r = sd_bus_message_read(message, "b", &b);
437 if (r < 0)
438 return r;
439
440 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
441 *p = b;
442 unit_invalidate_cgroup(u, mask);
443 unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
444 }
445
446 return 1;
447 }
448
449 #define BUS_DEFINE_SET_CGROUP_WEIGHT(function, mask, check, val) \
450 static int bus_cgroup_set_##function( \
451 Unit *u, \
452 const char *name, \
453 uint64_t *p, \
454 sd_bus_message *message, \
455 UnitWriteFlags flags, \
456 sd_bus_error *error) { \
457 \
458 uint64_t v; \
459 int r; \
460 \
461 assert(p); \
462 \
463 r = sd_bus_message_read(message, "t", &v); \
464 if (r < 0) \
465 return r; \
466 \
467 if (!check(v)) \
468 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
469 "Value specified in %s is out of range", name); \
470 \
471 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
472 *p = v; \
473 unit_invalidate_cgroup(u, (mask)); \
474 \
475 if (v == (val)) \
476 unit_write_settingf(u, flags, name, \
477 "%s=", name); \
478 else \
479 unit_write_settingf(u, flags, name, \
480 "%s=%" PRIu64, name, v); \
481 } \
482 \
483 return 1; \
484 }
485
486 #define BUS_DEFINE_SET_CGROUP_LIMIT(function, mask, scale, minimum) \
487 static int bus_cgroup_set_##function( \
488 Unit *u, \
489 const char *name, \
490 uint64_t *p, \
491 sd_bus_message *message, \
492 UnitWriteFlags flags, \
493 sd_bus_error *error) { \
494 \
495 uint64_t v; \
496 int r; \
497 \
498 assert(p); \
499 \
500 r = sd_bus_message_read(message, "t", &v); \
501 if (r < 0) \
502 return r; \
503 \
504 if (v < minimum) \
505 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
506 "Value specified in %s is out of range", name); \
507 \
508 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
509 *p = v; \
510 unit_invalidate_cgroup(u, (mask)); \
511 \
512 if (v == CGROUP_LIMIT_MAX) \
513 unit_write_settingf(u, flags, name, \
514 "%s=infinity", name); \
515 else \
516 unit_write_settingf(u, flags, name, \
517 "%s=%" PRIu64, name, v); \
518 } \
519 \
520 return 1; \
521 } \
522 static int bus_cgroup_set_##function##_scale( \
523 Unit *u, \
524 const char *name, \
525 uint64_t *p, \
526 sd_bus_message *message, \
527 UnitWriteFlags flags, \
528 sd_bus_error *error) { \
529 \
530 uint64_t v; \
531 uint32_t raw; \
532 int r; \
533 \
534 assert(p); \
535 \
536 r = sd_bus_message_read(message, "u", &raw); \
537 if (r < 0) \
538 return r; \
539 \
540 v = scale(raw, UINT32_MAX); \
541 if (v < minimum || v >= UINT64_MAX) \
542 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, \
543 "Value specified in %s is out of range", name); \
544 \
545 if (!UNIT_WRITE_FLAGS_NOOP(flags)) { \
546 const char *e; \
547 \
548 *p = v; \
549 unit_invalidate_cgroup(u, (mask)); \
550 \
551 /* Chop off suffix */ \
552 assert_se(e = endswith(name, "Scale")); \
553 name = strndupa(name, e - name); \
554 \
555 unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name, \
556 (uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX))); \
557 } \
558 \
559 return 1; \
560 }
561
562 #pragma GCC diagnostic push
563 #pragma GCC diagnostic ignored "-Wtype-limits"
564 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_weight, CGROUP_MASK_CPU, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
565 BUS_DEFINE_SET_CGROUP_WEIGHT(cpu_shares, CGROUP_MASK_CPU, CGROUP_CPU_SHARES_IS_OK, CGROUP_CPU_SHARES_INVALID);
566 BUS_DEFINE_SET_CGROUP_WEIGHT(io_weight, CGROUP_MASK_IO, CGROUP_WEIGHT_IS_OK, CGROUP_WEIGHT_INVALID);
567 BUS_DEFINE_SET_CGROUP_WEIGHT(blockio_weight, CGROUP_MASK_BLKIO, CGROUP_BLKIO_WEIGHT_IS_OK, CGROUP_BLKIO_WEIGHT_INVALID);
568 BUS_DEFINE_SET_CGROUP_LIMIT(memory, CGROUP_MASK_MEMORY, physical_memory_scale, 1);
569 BUS_DEFINE_SET_CGROUP_LIMIT(swap, CGROUP_MASK_MEMORY, physical_memory_scale, 0);
570 BUS_DEFINE_SET_CGROUP_LIMIT(tasks_max, CGROUP_MASK_PIDS, system_tasks_max_scale, 1);
571 #pragma GCC diagnostic pop
572
573 int bus_cgroup_set_property(
574 Unit *u,
575 CGroupContext *c,
576 const char *name,
577 sd_bus_message *message,
578 UnitWriteFlags flags,
579 sd_bus_error *error) {
580
581 CGroupIOLimitType iol_type;
582 int r;
583
584 assert(u);
585 assert(c);
586 assert(name);
587 assert(message);
588
589 flags |= UNIT_PRIVATE;
590
591 if (streq(name, "CPUAccounting"))
592 return bus_cgroup_set_boolean(u, name, &c->cpu_accounting, CGROUP_MASK_CPUACCT|CGROUP_MASK_CPU, message, flags, error);
593
594 if (streq(name, "CPUWeight"))
595 return bus_cgroup_set_cpu_weight(u, name, &c->cpu_weight, message, flags, error);
596
597 if (streq(name, "StartupCPUWeight"))
598 return bus_cgroup_set_cpu_weight(u, name, &c->startup_cpu_weight, message, flags, error);
599
600 if (streq(name, "CPUShares"))
601 return bus_cgroup_set_cpu_shares(u, name, &c->cpu_shares, message, flags, error);
602
603 if (streq(name, "StartupCPUShares"))
604 return bus_cgroup_set_cpu_shares(u, name, &c->startup_cpu_shares, message, flags, error);
605
606 if (streq(name, "IOAccounting"))
607 return bus_cgroup_set_boolean(u, name, &c->io_accounting, CGROUP_MASK_IO, message, flags, error);
608
609 if (streq(name, "IOWeight"))
610 return bus_cgroup_set_io_weight(u, name, &c->io_weight, message, flags, error);
611
612 if (streq(name, "StartupIOWeight"))
613 return bus_cgroup_set_io_weight(u, name, &c->startup_io_weight, message, flags, error);
614
615 if (streq(name, "BlockIOAccounting"))
616 return bus_cgroup_set_boolean(u, name, &c->blockio_accounting, CGROUP_MASK_BLKIO, message, flags, error);
617
618 if (streq(name, "BlockIOWeight"))
619 return bus_cgroup_set_blockio_weight(u, name, &c->blockio_weight, message, flags, error);
620
621 if (streq(name, "StartupBlockIOWeight"))
622 return bus_cgroup_set_blockio_weight(u, name, &c->startup_blockio_weight, message, flags, error);
623
624 if (streq(name, "MemoryAccounting"))
625 return bus_cgroup_set_boolean(u, name, &c->memory_accounting, CGROUP_MASK_MEMORY, message, flags, error);
626
627 if (streq(name, "MemoryLow"))
628 return bus_cgroup_set_memory(u, name, &c->memory_low, message, flags, error);
629
630 if (streq(name, "MemoryHigh"))
631 return bus_cgroup_set_memory(u, name, &c->memory_high, message, flags, error);
632
633 if (streq(name, "MemorySwapMax"))
634 return bus_cgroup_set_swap(u, name, &c->memory_swap_max, message, flags, error);
635
636 if (streq(name, "MemoryMax"))
637 return bus_cgroup_set_memory(u, name, &c->memory_max, message, flags, error);
638
639 if (streq(name, "MemoryLimit"))
640 return bus_cgroup_set_memory(u, name, &c->memory_limit, message, flags, error);
641
642 if (streq(name, "MemoryLowScale"))
643 return bus_cgroup_set_memory_scale(u, name, &c->memory_low, message, flags, error);
644
645 if (streq(name, "MemoryHighScale"))
646 return bus_cgroup_set_memory_scale(u, name, &c->memory_high, message, flags, error);
647
648 if (streq(name, "MemorySwapMaxScale"))
649 return bus_cgroup_set_swap_scale(u, name, &c->memory_swap_max, message, flags, error);
650
651 if (streq(name, "MemoryMaxScale"))
652 return bus_cgroup_set_memory_scale(u, name, &c->memory_max, message, flags, error);
653
654 if (streq(name, "MemoryLimitScale"))
655 return bus_cgroup_set_memory_scale(u, name, &c->memory_limit, message, flags, error);
656
657 if (streq(name, "TasksAccounting"))
658 return bus_cgroup_set_boolean(u, name, &c->tasks_accounting, CGROUP_MASK_PIDS, message, flags, error);
659
660 if (streq(name, "TasksMax"))
661 return bus_cgroup_set_tasks_max(u, name, &c->tasks_max, message, flags, error);
662
663 if (streq(name, "TasksMaxScale"))
664 return bus_cgroup_set_tasks_max_scale(u, name, &c->tasks_max, message, flags, error);
665
666 if (streq(name, "CPUQuotaPerSecUSec")) {
667 uint64_t u64;
668
669 r = sd_bus_message_read(message, "t", &u64);
670 if (r < 0)
671 return r;
672
673 if (u64 <= 0)
674 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUQuotaPerSecUSec= value out of range");
675
676 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
677 c->cpu_quota_per_sec_usec = u64;
678 unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
679
680 if (c->cpu_quota_per_sec_usec == USEC_INFINITY)
681 unit_write_setting(u, flags, "CPUQuota", "CPUQuota=");
682 else
683 /* config_parse_cpu_quota() requires an integer, so truncating division is used on
684 * purpose here. */
685 unit_write_settingf(u, flags, "CPUQuota",
686 "CPUQuota=%0.f%%",
687 (double) (c->cpu_quota_per_sec_usec / 10000));
688 }
689
690 return 1;
691
692 } else if ((iol_type = cgroup_io_limit_type_from_string(name)) >= 0) {
693 const char *path;
694 unsigned n = 0;
695 uint64_t u64;
696
697 r = sd_bus_message_enter_container(message, 'a', "(st)");
698 if (r < 0)
699 return r;
700
701 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
702
703 if (!path_startswith(path, "/dev") &&
704 !path_startswith(path, "/run/systemd/inaccessible/"))
705 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
706
707 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
708 CGroupIODeviceLimit *a = NULL, *b;
709
710 LIST_FOREACH(device_limits, b, c->io_device_limits) {
711 if (path_equal(path, b->path)) {
712 a = b;
713 break;
714 }
715 }
716
717 if (!a) {
718 CGroupIOLimitType type;
719
720 a = new0(CGroupIODeviceLimit, 1);
721 if (!a)
722 return -ENOMEM;
723
724 a->path = strdup(path);
725 if (!a->path) {
726 free(a);
727 return -ENOMEM;
728 }
729
730 for (type = 0; type < _CGROUP_IO_LIMIT_TYPE_MAX; type++)
731 a->limits[type] = cgroup_io_limit_defaults[type];
732
733 LIST_PREPEND(device_limits, c->io_device_limits, a);
734 }
735
736 a->limits[iol_type] = u64;
737 }
738
739 n++;
740 }
741 if (r < 0)
742 return r;
743
744 r = sd_bus_message_exit_container(message);
745 if (r < 0)
746 return r;
747
748 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
749 CGroupIODeviceLimit *a;
750 _cleanup_free_ char *buf = NULL;
751 _cleanup_fclose_ FILE *f = NULL;
752 size_t size = 0;
753
754 if (n == 0) {
755 LIST_FOREACH(device_limits, a, c->io_device_limits)
756 a->limits[iol_type] = cgroup_io_limit_defaults[iol_type];
757 }
758
759 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
760
761 f = open_memstream(&buf, &size);
762 if (!f)
763 return -ENOMEM;
764
765 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
766
767 fprintf(f, "%s=\n", name);
768 LIST_FOREACH(device_limits, a, c->io_device_limits)
769 if (a->limits[iol_type] != cgroup_io_limit_defaults[iol_type])
770 fprintf(f, "%s=%s %" PRIu64 "\n", name, a->path, a->limits[iol_type]);
771
772 r = fflush_and_check(f);
773 if (r < 0)
774 return r;
775 unit_write_setting(u, flags, name, buf);
776 }
777
778 return 1;
779
780 } else if (streq(name, "IODeviceWeight")) {
781 const char *path;
782 uint64_t weight;
783 unsigned n = 0;
784
785 r = sd_bus_message_enter_container(message, 'a', "(st)");
786 if (r < 0)
787 return r;
788
789 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
790
791 if (!path_startswith(path, "/dev") &&
792 !path_startswith(path, "/run/systemd/inaccessible/"))
793 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
794
795 if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
796 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
797
798 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
799 CGroupIODeviceWeight *a = NULL, *b;
800
801 LIST_FOREACH(device_weights, b, c->io_device_weights) {
802 if (path_equal(b->path, path)) {
803 a = b;
804 break;
805 }
806 }
807
808 if (!a) {
809 a = new0(CGroupIODeviceWeight, 1);
810 if (!a)
811 return -ENOMEM;
812
813 a->path = strdup(path);
814 if (!a->path) {
815 free(a);
816 return -ENOMEM;
817 }
818 LIST_PREPEND(device_weights, c->io_device_weights, a);
819 }
820
821 a->weight = weight;
822 }
823
824 n++;
825 }
826
827 r = sd_bus_message_exit_container(message);
828 if (r < 0)
829 return r;
830
831 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
832 _cleanup_free_ char *buf = NULL;
833 _cleanup_fclose_ FILE *f = NULL;
834 CGroupIODeviceWeight *a;
835 size_t size = 0;
836
837 if (n == 0) {
838 while (c->io_device_weights)
839 cgroup_context_free_io_device_weight(c, c->io_device_weights);
840 }
841
842 unit_invalidate_cgroup(u, CGROUP_MASK_IO);
843
844 f = open_memstream(&buf, &size);
845 if (!f)
846 return -ENOMEM;
847
848 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
849
850 fputs("IODeviceWeight=\n", f);
851 LIST_FOREACH(device_weights, a, c->io_device_weights)
852 fprintf(f, "IODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
853
854 r = fflush_and_check(f);
855 if (r < 0)
856 return r;
857 unit_write_setting(u, flags, name, buf);
858 }
859
860 return 1;
861
862 } else if (STR_IN_SET(name, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
863 const char *path;
864 bool read = true;
865 unsigned n = 0;
866 uint64_t u64;
867
868 if (streq(name, "BlockIOWriteBandwidth"))
869 read = false;
870
871 r = sd_bus_message_enter_container(message, 'a', "(st)");
872 if (r < 0)
873 return r;
874
875 while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
876
877 if (!path_startswith(path, "/dev") &&
878 !path_startswith(path, "/run/systemd/inaccessible/"))
879 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
880
881 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
882 CGroupBlockIODeviceBandwidth *a = NULL, *b;
883
884 LIST_FOREACH(device_bandwidths, b, c->blockio_device_bandwidths) {
885 if (path_equal(path, b->path)) {
886 a = b;
887 break;
888 }
889 }
890
891 if (!a) {
892 a = new0(CGroupBlockIODeviceBandwidth, 1);
893 if (!a)
894 return -ENOMEM;
895
896 a->rbps = CGROUP_LIMIT_MAX;
897 a->wbps = CGROUP_LIMIT_MAX;
898 a->path = strdup(path);
899 if (!a->path) {
900 free(a);
901 return -ENOMEM;
902 }
903
904 LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, a);
905 }
906
907 if (read)
908 a->rbps = u64;
909 else
910 a->wbps = u64;
911 }
912
913 n++;
914 }
915 if (r < 0)
916 return r;
917
918 r = sd_bus_message_exit_container(message);
919 if (r < 0)
920 return r;
921
922 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
923 CGroupBlockIODeviceBandwidth *a;
924 _cleanup_free_ char *buf = NULL;
925 _cleanup_fclose_ FILE *f = NULL;
926 size_t size = 0;
927
928 if (n == 0) {
929 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths) {
930 if (read)
931 a->rbps = CGROUP_LIMIT_MAX;
932 else
933 a->wbps = CGROUP_LIMIT_MAX;
934 }
935 }
936
937 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
938
939 f = open_memstream(&buf, &size);
940 if (!f)
941 return -ENOMEM;
942
943 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
944
945 if (read) {
946 fputs("BlockIOReadBandwidth=\n", f);
947 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
948 if (a->rbps != CGROUP_LIMIT_MAX)
949 fprintf(f, "BlockIOReadBandwidth=%s %" PRIu64 "\n", a->path, a->rbps);
950 } else {
951 fputs("BlockIOWriteBandwidth=\n", f);
952 LIST_FOREACH(device_bandwidths, a, c->blockio_device_bandwidths)
953 if (a->wbps != CGROUP_LIMIT_MAX)
954 fprintf(f, "BlockIOWriteBandwidth=%s %" PRIu64 "\n", a->path, a->wbps);
955 }
956
957 r = fflush_and_check(f);
958 if (r < 0)
959 return r;
960
961 unit_write_setting(u, flags, name, buf);
962 }
963
964 return 1;
965
966 } else if (streq(name, "BlockIODeviceWeight")) {
967 const char *path;
968 uint64_t weight;
969 unsigned n = 0;
970
971 r = sd_bus_message_enter_container(message, 'a', "(st)");
972 if (r < 0)
973 return r;
974
975 while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
976
977 if (!path_startswith(path, "/dev") &&
978 !path_startswith(path, "/run/systemd/inaccessible/"))
979 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
980
981 if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
982 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
983
984 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
985 CGroupBlockIODeviceWeight *a = NULL, *b;
986
987 LIST_FOREACH(device_weights, b, c->blockio_device_weights) {
988 if (path_equal(b->path, path)) {
989 a = b;
990 break;
991 }
992 }
993
994 if (!a) {
995 a = new0(CGroupBlockIODeviceWeight, 1);
996 if (!a)
997 return -ENOMEM;
998
999 a->path = strdup(path);
1000 if (!a->path) {
1001 free(a);
1002 return -ENOMEM;
1003 }
1004 LIST_PREPEND(device_weights, c->blockio_device_weights, a);
1005 }
1006
1007 a->weight = weight;
1008 }
1009
1010 n++;
1011 }
1012
1013 r = sd_bus_message_exit_container(message);
1014 if (r < 0)
1015 return r;
1016
1017 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1018 _cleanup_free_ char *buf = NULL;
1019 _cleanup_fclose_ FILE *f = NULL;
1020 CGroupBlockIODeviceWeight *a;
1021 size_t size = 0;
1022
1023 if (n == 0) {
1024 while (c->blockio_device_weights)
1025 cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
1026 }
1027
1028 unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
1029
1030 f = open_memstream(&buf, &size);
1031 if (!f)
1032 return -ENOMEM;
1033
1034 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1035
1036 fputs("BlockIODeviceWeight=\n", f);
1037 LIST_FOREACH(device_weights, a, c->blockio_device_weights)
1038 fprintf(f, "BlockIODeviceWeight=%s %" PRIu64 "\n", a->path, a->weight);
1039
1040 r = fflush_and_check(f);
1041 if (r < 0)
1042 return r;
1043
1044 unit_write_setting(u, flags, name, buf);
1045 }
1046
1047 return 1;
1048
1049 } else if (streq(name, "DevicePolicy")) {
1050 const char *policy;
1051 CGroupDevicePolicy p;
1052
1053 r = sd_bus_message_read(message, "s", &policy);
1054 if (r < 0)
1055 return r;
1056
1057 p = cgroup_device_policy_from_string(policy);
1058 if (p < 0)
1059 return -EINVAL;
1060
1061 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1062 c->device_policy = p;
1063 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1064 unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
1065 }
1066
1067 return 1;
1068
1069 } else if (streq(name, "DeviceAllow")) {
1070 const char *path, *rwm;
1071 unsigned n = 0;
1072
1073 r = sd_bus_message_enter_container(message, 'a', "(ss)");
1074 if (r < 0)
1075 return r;
1076
1077 while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
1078
1079 if ((!is_deviceallow_pattern(path) &&
1080 !path_startswith(path, "/run/systemd/inaccessible/")) ||
1081 strpbrk(path, WHITESPACE))
1082 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
1083
1084 if (isempty(rwm))
1085 rwm = "rwm";
1086
1087 if (!in_charset(rwm, "rwm"))
1088 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires combination of rwm flags");
1089
1090 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1091 CGroupDeviceAllow *a = NULL, *b;
1092
1093 LIST_FOREACH(device_allow, b, c->device_allow) {
1094 if (path_equal(b->path, path)) {
1095 a = b;
1096 break;
1097 }
1098 }
1099
1100 if (!a) {
1101 a = new0(CGroupDeviceAllow, 1);
1102 if (!a)
1103 return -ENOMEM;
1104
1105 a->path = strdup(path);
1106 if (!a->path) {
1107 free(a);
1108 return -ENOMEM;
1109 }
1110
1111 LIST_PREPEND(device_allow, c->device_allow, a);
1112 }
1113
1114 a->r = !!strchr(rwm, 'r');
1115 a->w = !!strchr(rwm, 'w');
1116 a->m = !!strchr(rwm, 'm');
1117 }
1118
1119 n++;
1120 }
1121 if (r < 0)
1122 return r;
1123
1124 r = sd_bus_message_exit_container(message);
1125 if (r < 0)
1126 return r;
1127
1128 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1129 _cleanup_free_ char *buf = NULL;
1130 _cleanup_fclose_ FILE *f = NULL;
1131 CGroupDeviceAllow *a;
1132 size_t size = 0;
1133
1134 if (n == 0) {
1135 while (c->device_allow)
1136 cgroup_context_free_device_allow(c, c->device_allow);
1137 }
1138
1139 unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
1140
1141 f = open_memstream(&buf, &size);
1142 if (!f)
1143 return -ENOMEM;
1144
1145 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1146
1147 fputs("DeviceAllow=\n", f);
1148 LIST_FOREACH(device_allow, a, c->device_allow)
1149 fprintf(f, "DeviceAllow=%s %s%s%s\n", a->path, a->r ? "r" : "", a->w ? "w" : "", a->m ? "m" : "");
1150
1151 r = fflush_and_check(f);
1152 if (r < 0)
1153 return r;
1154 unit_write_setting(u, flags, name, buf);
1155 }
1156
1157 return 1;
1158
1159 } else if (streq(name, "IPAccounting")) {
1160 int b;
1161
1162 r = sd_bus_message_read(message, "b", &b);
1163 if (r < 0)
1164 return r;
1165
1166 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1167 c->ip_accounting = b;
1168
1169 unit_invalidate_cgroup_bpf(u);
1170 unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
1171 }
1172
1173 return 1;
1174
1175 } else if (STR_IN_SET(name, "IPAddressAllow", "IPAddressDeny")) {
1176 IPAddressAccessItem **list;
1177 size_t n = 0;
1178
1179 list = streq(name, "IPAddressAllow") ? &c->ip_address_allow : &c->ip_address_deny;
1180
1181 r = sd_bus_message_enter_container(message, 'a', "(iayu)");
1182 if (r < 0)
1183 return r;
1184
1185 for (;;) {
1186 const void *ap;
1187 int32_t family;
1188 uint32_t prefixlen;
1189 size_t an;
1190
1191 r = sd_bus_message_enter_container(message, 'r', "iayu");
1192 if (r < 0)
1193 return r;
1194 if (r == 0)
1195 break;
1196
1197 r = sd_bus_message_read(message, "i", &family);
1198 if (r < 0)
1199 return r;
1200
1201 if (!IN_SET(family, AF_INET, AF_INET6))
1202 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= expects IPv4 or IPv6 addresses only.", name);
1203
1204 r = sd_bus_message_read_array(message, 'y', &ap, &an);
1205 if (r < 0)
1206 return r;
1207
1208 if (an != FAMILY_ADDRESS_SIZE(family))
1209 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IP address has wrong size for family (%s, expected %zu, got %zu)",
1210 af_to_name(family), FAMILY_ADDRESS_SIZE(family), an);
1211
1212 r = sd_bus_message_read(message, "u", &prefixlen);
1213 if (r < 0)
1214 return r;
1215
1216 if (prefixlen > FAMILY_ADDRESS_SIZE(family)*8)
1217 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Prefix length %" PRIu32 " too large for address family %s.", prefixlen, af_to_name(family));
1218
1219 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1220 IPAddressAccessItem *item;
1221
1222 item = new0(IPAddressAccessItem, 1);
1223 if (!item)
1224 return -ENOMEM;
1225
1226 item->family = family;
1227 item->prefixlen = prefixlen;
1228 memcpy(&item->address, ap, an);
1229
1230 LIST_PREPEND(items, *list, item);
1231 }
1232
1233 r = sd_bus_message_exit_container(message);
1234 if (r < 0)
1235 return r;
1236
1237 n++;
1238 }
1239
1240 r = sd_bus_message_exit_container(message);
1241 if (r < 0)
1242 return r;
1243
1244 *list = ip_address_access_reduce(*list);
1245
1246 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
1247 _cleanup_free_ char *buf = NULL;
1248 _cleanup_fclose_ FILE *f = NULL;
1249 IPAddressAccessItem *item;
1250 size_t size = 0;
1251
1252 if (n == 0)
1253 *list = ip_address_access_free_all(*list);
1254
1255 unit_invalidate_cgroup_bpf(u);
1256 f = open_memstream(&buf, &size);
1257 if (!f)
1258 return -ENOMEM;
1259
1260 (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
1261
1262 fputs(name, f);
1263 fputs("=\n", f);
1264
1265 LIST_FOREACH(items, item, *list) {
1266 char buffer[CONST_MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
1267
1268 errno = 0;
1269 if (!inet_ntop(item->family, &item->address, buffer, sizeof(buffer)))
1270 return errno > 0 ? -errno : -EINVAL;
1271
1272 fprintf(f, "%s=%s/%u\n", name, buffer, item->prefixlen);
1273 }
1274
1275 r = fflush_and_check(f);
1276 if (r < 0)
1277 return r;
1278
1279 unit_write_setting(u, flags, name, buf);
1280
1281 if (*list) {
1282 r = bpf_firewall_supported();
1283 if (r < 0)
1284 return r;
1285 if (r == BPF_FIREWALL_UNSUPPORTED) {
1286 static bool warned = false;
1287
1288 log_full(warned ? LOG_DEBUG : LOG_WARNING,
1289 "Transient unit %s configures an IP firewall, but the local system does not support BPF/cgroup firewalling.\n"
1290 "Proceeding WITHOUT firewalling in effect! (This warning is only shown for the first started transient unit using IP firewalling.)", u->id);
1291
1292 warned = true;
1293 }
1294 }
1295 }
1296
1297 return 1;
1298 }
1299
1300 if (u->transient && u->load_state == UNIT_STUB)
1301 return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
1302
1303 return 0;
1304 }