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