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